Skip to content

Commit

Permalink
refactor: split copy / marshal
Browse files Browse the repository at this point in the history
  • Loading branch information
secDre4mer committed May 3, 2024
1 parent 318f32c commit c3bf0ff
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 15 deletions.
25 changes: 25 additions & 0 deletions marshal.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package pkcs7

import "encoding/asn1"

func (p7 *PKCS7) Marshal() ([]byte, error) {
var contentType asn1.ObjectIdentifier
switch p7.raw.(type) {
case signedData:
contentType = OIDSignedData
case envelopedData:
contentType = OIDEnvelopedData
case encryptedData:
contentType = OIDEncryptedData
default:
return nil, ErrUnsupportedContentType
}
inner, err := asn1.Marshal(p7.raw)
if err != nil {
return nil, err
}
return asn1.Marshal(contentInfo{
ContentType: contentType,
Content: asn1.RawValue{Class: 2, Tag: 0, Bytes: inner, IsCompound: true},
})
}
60 changes: 60 additions & 0 deletions marshal_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package pkcs7

import (
"bytes"
"crypto/x509"
"encoding/pem"
"os"
"testing"
)

func TestPKCS7_Marshal(t *testing.T) {
content := []byte("Hello World")
rootCert, err := createTestCertificateByIssuer("PKCS7 Test Root CA", nil, x509.SHA256WithRSA, true)
if err != nil {
t.Fatalf("cannot generate root cert: %s", err)
}
truststore := x509.NewCertPool()
truststore.AddCert(rootCert.Certificate)
signerCert, err := createTestCertificateByIssuer("PKCS7 Test Signer Cert", rootCert, x509.SHA256WithRSA, false)
if err != nil {
t.Fatalf("cannot generate signer cert: %s", err)
}
toBeSigned, err := NewSignedData(content)
if err != nil {
t.Fatalf("cannot initialize signed data: %s", err)
}

// Set the digest to match the end entity cert
signerDigest, _ := getDigestOIDForSignatureAlgorithm(signerCert.Certificate.SignatureAlgorithm)
toBeSigned.SetDigestAlgorithm(signerDigest)

if err := toBeSigned.AddSignerChain(signerCert.Certificate, *signerCert.PrivateKey, nil, SignerInfoConfig{}); err != nil {
t.Fatalf("cannot add signer: %s", err)
}
signed, err := toBeSigned.Finish()
if err != nil {
t.Fatalf("cannot finish signing data: %s", err)
}
pem.Encode(os.Stdout, &pem.Block{Type: "PKCS7", Bytes: signed})

p7, err := Parse(signed)
if err != nil {
t.Fatalf("cannot parse signed data: %s", err)
}

marshaled, err := p7.Marshal()
if err != nil {
t.Fatalf("cannot marshal signed data: %s", err)
}
p7Reparsed, err := Parse(marshaled)
if err != nil {
t.Fatalf("cannot reparse signed data: %s", err)
}
if !bytes.Equal(p7.Content, p7Reparsed.Content) {
t.Errorf("content was not found in the reparsed data:\n\tExpected: %s\n\tActual: %s", p7.Content, p7Reparsed.Content)
}
if err := p7Reparsed.VerifyWithChain(truststore); err != nil {
t.Errorf("cannot verify reparsed data: %s", err)
}
}
20 changes: 11 additions & 9 deletions sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ type SignedData struct {
encryptionOid asn1.ObjectIdentifier
}

// Copy creates a new SignedData struct based on existing PKCS7 signed data.
func Copy(data *PKCS7, unauthenticatedAttrs ...Attribute) ([]byte, error) {
rawData, isSignedData := data.raw.(signedData)
// CopyWithUnsignedAttributes creates a copy of the PKCS7 struct with different unsigned attributes.
func (p7 *PKCS7) CopyWithUnsignedAttributes(unauthenticatedAttrs ...Attribute) (*PKCS7, error) {
rawData, isSignedData := p7.raw.(signedData)
if !isSignedData {
return nil, ErrUnsupportedContentType
}
Expand All @@ -38,15 +38,17 @@ func Copy(data *PKCS7, unauthenticatedAttrs ...Attribute) ([]byte, error) {
return nil, err
}
}
inner, err := asn1.Marshal(rawData)
certs, err := rawData.Certificates.Parse()
if err != nil {
return nil, err
}
outer := contentInfo{
ContentType: OIDSignedData,
Content: asn1.RawValue{Class: 2, Tag: 0, Bytes: inner, IsCompound: true},
}
return asn1.Marshal(outer)
return &PKCS7{
Content: p7.Content,
Certificates: certs,
CRLs: rawData.CRLs,
Signers: rawData.SignerInfos,
raw: rawData,
}, nil
}

// NewSignedData takes data and initializes a PKCS7 SignedData struct that is
Expand Down
8 changes: 2 additions & 6 deletions sign_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ func fromHex(s string) *big.Int {
return result
}

func TestCopy(t *testing.T) {
func TestCopyWithUnsignedAttributes(t *testing.T) {
content := []byte("Hello World")
rootCert, err := createTestCertificateByIssuer("PKCS7 Test Root CA", nil, x509.SHA256WithRSA, true)
if err != nil {
Expand Down Expand Up @@ -301,17 +301,13 @@ func TestCopy(t *testing.T) {
}
testOid := asn1.ObjectIdentifier{2, 3, 4, 5, 6, 7}
testValue := "TestValue"
copied, err := Copy(p7, Attribute{
p7, err = p7.CopyWithUnsignedAttributes(Attribute{
Type: testOid,
Value: testValue,
})
if err != nil {
t.Fatalf("cannot copy signed data: %s", err)
}
p7, err = Parse(copied)
if err != nil {
t.Fatalf("cannot parse copied data: %s", err)
}

if !bytes.Equal(content, p7.Content) {
t.Errorf("content was not found in the copied data:\n\tExpected: %s\n\tActual: %s", content, p7.Content)
Expand Down

0 comments on commit c3bf0ff

Please sign in to comment.