Documentation
¶
Overview ¶
Package pkcs7 implements parsing and generation of PKCS#7 / CMS structures as defined in RFC 5652 (Cryptographic Message Syntax).
Supported content types:
- SignedData (OID 1.2.840.113549.1.7.2) — RFC 5652 §5
- EnvelopedData (OID 1.2.840.113549.1.7.3) — RFC 5652 §6
- EncryptedData (OID 1.2.840.113549.1.7.6) — RFC 5652 §8
Not yet implemented:
- DigestedData (OID 1.2.840.113549.1.7.5) — RFC 5652 §7
- AuthenticatedData (OID 1.2.840.113549.1.9.16.1.2) — RFC 5652 §9
- SubjectKeyIdentifier as SignerIdentifier — RFC 5652 §5.3
- KeyAgreeRecipientInfo (ECDH key agreement) — RFC 5652 §6.2.2
- KEKRecipientInfo (pre-distributed symmetric keys) — RFC 5652 §6.2.3
- PasswordRecipientInfo — RFC 5652 §6.2.4
- RSA-OAEP key transport — RFC 3560
Index ¶
- Constants
- Variables
- func CheckSignature(cert *x509.Certificate, signer SignerInfo, content []byte) error
- func DegenerateCertificate(cert []byte) ([]byte, error)
- func DigestOIDForSignatureAlgorithm(digestAlg x509.SignatureAlgorithm) (asn1.ObjectIdentifier, error)
- func Encrypt(content []byte, recipients []*x509.Certificate) ([]byte, error)
- func EncryptUsingPSK(content []byte, key []byte) ([]byte, error)
- func GetCertFromCertsByIssuerAndSerial(certs []*x509.Certificate, ias issuerAndSerial) *x509.Certificate
- func HashForOID(oid asn1.ObjectIdentifier) (crypto.Hash, error)
- func OIDForEncryptionAlgorithm(pkey crypto.PrivateKey, OIDDigestAlg asn1.ObjectIdentifier) (asn1.ObjectIdentifier, error)
- func VerifyCertChain(ee *x509.Certificate, certs []*x509.Certificate, truststore *x509.CertPool, ...) (chains [][]*x509.Certificate, err error)
- func VerifyMessageDigestDetached(signer SignerInfo, signedData []byte) error
- func VerifyMessageDigestEmbedded(oidDigestAlg asn1.ObjectIdentifier, digest, signedData []byte) error
- func VerifyMessageDigestTSToken(oidHashAlg asn1.ObjectIdentifier, digest, signedData []byte) error
- type Attribute
- type ESSCertID
- type ESSCertIDv2
- type MessageDigestMismatchError
- type PKCS7
- func (p7 *PKCS7) Decrypt(cert *x509.Certificate, pkey crypto.PrivateKey) ([]byte, error)
- func (p7 *PKCS7) DecryptUsingPSK(key []byte) ([]byte, error)
- func (p7 *PKCS7) GetOnlySigner() *x509.Certificate
- func (p7 *PKCS7) UnmarshalSignedAttribute(attributeType asn1.ObjectIdentifier, out interface{}) error
- func (p7 *PKCS7) Verify() (err error)
- func (p7 *PKCS7) VerifyWithChain(truststore *x509.CertPool) (err error)
- func (p7 *PKCS7) VerifyWithChainAtTime(truststore *x509.CertPool, currentTime time.Time) (err error)
- type SignedData
- func (sd *SignedData) AddCertificate(cert *x509.Certificate)
- func (sd *SignedData) AddSigner(cert *x509.Certificate, pkey crypto.PrivateKey, messageDigest []byte, ...) error
- func (sd *SignedData) AddSignerChain(cert *x509.Certificate, pkey crypto.PrivateKey, messageDigest []byte, ...) error
- func (sd *SignedData) Detach()
- func (sd *SignedData) Finish() ([]byte, error)
- func (sd *SignedData) GetSignedData() *signedData
- func (sd *SignedData) SetContent(data []byte)
- type SignerInfo
- type SignerInfoConfig
- type SigningCertificate
- type SigningCertificateV2
Examples ¶
Constants ¶
const ( // EncryptionAlgorithmDESCBC is the DES CBC encryption algorithm EncryptionAlgorithmDESCBC = iota // EncryptionAlgorithmAES128CBC is the AES 128 bits with CBC encryption algorithm // Avoid this algorithm unless required for interoperability; use AES GCM instead. EncryptionAlgorithmAES128CBC // EncryptionAlgorithmAES256CBC is the AES 256 bits with CBC encryption algorithm // Avoid this algorithm unless required for interoperability; use AES GCM instead. EncryptionAlgorithmAES256CBC // EncryptionAlgorithmAES128GCM is the AES 128 bits with GCM encryption algorithm EncryptionAlgorithmAES128GCM // EncryptionAlgorithmAES256GCM is the AES 256 bits with GCM encryption algorithm EncryptionAlgorithmAES256GCM )
Variables ¶
var ( // Content type OIDs (RFC 5652 §4–§9) OIDData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 1} OIDSignedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 2} OIDEnvelopedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 3} OIDDigestedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 5} OIDEncryptedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 6} OIDAuthenticatedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 16, 1, 2} // Attribute OIDs (RFC 5652 §11) OIDAttributeContentType = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 3} OIDAttributeMessageDigest = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 4} OIDAttributeSigningTime = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 5} // Digest Algorithms OIDDigestAlgorithmSHA1 = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 26} OIDDigestAlgorithmSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 1} OIDDigestAlgorithmSHA384 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 2} OIDDigestAlgorithmSHA512 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 3} OIDDigestAlgorithmDSA = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 1} OIDDigestAlgorithmDSASHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3} OIDDigestAlgorithmECDSASHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1} OIDDigestAlgorithmECDSASHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2} OIDDigestAlgorithmECDSASHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3} OIDDigestAlgorithmECDSASHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4} // Signature Algorithms OIDEncryptionAlgorithmRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1} OIDEncryptionAlgorithmRSASHA1 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5} OIDEncryptionAlgorithmRSAPSS = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 10} OIDEncryptionAlgorithmRSASHA256 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11} OIDEncryptionAlgorithmRSASHA384 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12} OIDEncryptionAlgorithmRSASHA512 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13} OIDEncryptionAlgorithmECDSAP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7} // 256 bit elliptic curve OIDEncryptionAlgorithmECDSAP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34} // 384-bit elliptic curve OIDEncryptionAlgorithmECDSAP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35} // 512-bit elliptic curve! OIDEncryptionAlgorithmECPUBLICKEY = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1} // ecPublicKey OIDEncryptionAlgorithmDESCBC = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 7} OIDEncryptionAlgorithmDESEDE3CBC = asn1.ObjectIdentifier{1, 2, 840, 113549, 3, 7} OIDEncryptionAlgorithmAES256CBC = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 42} OIDEncryptionAlgorithmAES128GCM = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 6} OIDEncryptionAlgorithmAES128CBC = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 2} OIDEncryptionAlgorithmAES256GCM = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 46} OIDEncryptionAlgorithmECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2} OIDEncryptionAlgorithmECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3} OIDEncryptionAlgorithmECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4} OIDEncryptionAlgorithmEd25519 = asn1.ObjectIdentifier{1, 3, 101, 112} // Elliptic curve names OIDCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7} OIDCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34} OIDCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35} )
var ContentEncryptionAlgorithm = EncryptionAlgorithmDESCBC
ContentEncryptionAlgorithm determines the algorithm used to encrypt the plaintext message. Change the value of this variable to change which algorithm is used in the Encrypt() function.
var ErrNotEncryptedContent = errors.New("pkcs7: content is not an encrypted data type")
ErrNotEncryptedContent is returned when attempting to Decrypt data that is not encrypted data.
var ErrPSKNotProvided = errors.New("pkcs7: cannot encrypt content: PSK not provided")
ErrPSKNotProvided is returned when attempting to encrypt using a PSK without actually providing the PSK.
var ErrUnsupportedAlgorithm = errors.New("pkcs7: cannot decrypt data: only RSA, DES, DES-EDE3, AES-256-CBC and AES-128-GCM supported")
ErrUnsupportedAlgorithm tells you when our quick dev assumptions have failed
var ErrUnsupportedContentType = errors.New("pkcs7: cannot parse data: unimplemented content type")
ErrUnsupportedContentType is returned when a PKCS7 content is not supported. Currently only Data (1.2.840.113549.1.7.1), Signed Data (1.2.840.113549.1.7.2), and Enveloped Data are supported (1.2.840.113549.1.7.3)
var ErrUnsupportedEncryptionAlgorithm = errors.New("pkcs7: cannot encrypt content: only DES-CBC, AES-CBC, and AES-GCM supported")
ErrUnsupportedEncryptionAlgorithm is returned when attempting to encrypt content with an unsupported algorithm.
Functions ¶
func CheckSignature ¶
func CheckSignature(cert *x509.Certificate, signer SignerInfo, content []byte) error
CheckSignature verifies the cryptographic signature in signer using the public key from cert (RFC 5652 §5.6). If content is empty, the signature is verified over the DER-encoded authenticated attributes instead.
err := pkcs7.CheckSignature(signerCert, p7.Signers[0], nil)
func DegenerateCertificate ¶
DegenerateCertificate creates a SignedData structure containing only certificates and no signers (RFC 5652 §5.1). This is commonly used for certificate distribution.
der, err := pkcs7.DegenerateCertificate(cert.Raw)
func DigestOIDForSignatureAlgorithm ¶
func DigestOIDForSignatureAlgorithm(digestAlg x509.SignatureAlgorithm) (asn1.ObjectIdentifier, error)
DigestOIDForSignatureAlgorithm returns the digest algorithm OID for the given x509.SignatureAlgorithm. This is used to populate the digestAlgorithm field in SignerInfo (RFC 5652 §5.3).
oid, err := pkcs7.DigestOIDForSignatureAlgorithm(cert.SignatureAlgorithm)
func Encrypt ¶
func Encrypt(content []byte, recipients []*x509.Certificate) ([]byte, error)
Encrypt creates a CMS EnvelopedData structure (RFC 5652 §6) with the content encrypted under a random symmetric key, and that key encrypted for each recipient using RSA PKCS#1 v1.5 (KeyTransRecipientInfo, RFC 5652 §6.2.1).
Set ContentEncryptionAlgorithm before calling to control the cipher:
pkcs7.ContentEncryptionAlgorithm = pkcs7.EncryptionAlgorithmAES128GCM
encrypted, err := pkcs7.Encrypt(plaintext, []*x509.Certificate{recipientCert})
TODO: Support ECDH key agreement (KeyAgreeRecipientInfo, RFC 5652 §6.2.2). TODO: ContentEncryptionAlgorithm is a global variable and not safe for concurrent use. Consider passing it as a parameter.
func EncryptUsingPSK ¶
EncryptUsingPSK creates a CMS EncryptedData structure (RFC 5652 §8) using a pre-shared symmetric key. The key must match the expected size for the selected ContentEncryptionAlgorithm.
pkcs7.ContentEncryptionAlgorithm = pkcs7.EncryptionAlgorithmAES128GCM encrypted, err := pkcs7.EncryptUsingPSK(plaintext, aes128Key)
func GetCertFromCertsByIssuerAndSerial ¶
func GetCertFromCertsByIssuerAndSerial(certs []*x509.Certificate, ias issuerAndSerial) *x509.Certificate
GetCertFromCertsByIssuerAndSerial finds a certificate matching the given IssuerAndSerialNumber (RFC 5652 §5.3 SignerIdentifier). Returns nil if no match is found.
func HashForOID ¶
func HashForOID(oid asn1.ObjectIdentifier) (crypto.Hash, error)
HashForOID returns the crypto.Hash corresponding to the given digest algorithm OID. Supported OIDs include SHA-1, SHA-256, SHA-384, and SHA-512 (and their ECDSA/DSA combined variants).
hash, err := pkcs7.HashForOID(pkcs7.OIDDigestAlgorithmSHA256) h := hash.New() h.Write(data) digest := h.Sum(nil)
func OIDForEncryptionAlgorithm ¶
func OIDForEncryptionAlgorithm(pkey crypto.PrivateKey, OIDDigestAlg asn1.ObjectIdentifier) (asn1.ObjectIdentifier, error)
OIDForEncryptionAlgorithm returns the signature algorithm OID for the given private key type and digest algorithm OID. This maps to the signatureAlgorithm field in SignerInfo (RFC 5652 §5.3).
Supported key types: *rsa.PrivateKey, *ecdsa.PrivateKey.
func VerifyCertChain ¶
func VerifyCertChain(ee *x509.Certificate, certs []*x509.Certificate, truststore *x509.CertPool, currentTime time.Time) (chains [][]*x509.Certificate, err error)
VerifyCertChain builds and verifies certificate chains from the end-entity certificate to a trusted root via the provided intermediates. The currentTime parameter controls the time used for validity checks; use time.Time{} for now.
chains, err := pkcs7.VerifyCertChain(eeCert, intermediates, roots, time.Now())
func VerifyMessageDigestDetached ¶
func VerifyMessageDigestDetached(signer SignerInfo, signedData []byte) error
VerifyMessageDigestDetached verifies that the message-digest authenticated attribute in signer matches the hash of signedData (RFC 5652 §5.4). Use this for detached signatures where the content is supplied separately.
err := pkcs7.VerifyMessageDigestDetached(p7.Signers[0], originalContent)
func VerifyMessageDigestEmbedded ¶
func VerifyMessageDigestEmbedded(oidDigestAlg asn1.ObjectIdentifier, digest, signedData []byte) error
VerifyMessageDigestEmbedded verifies a message digest for embedded signatures without authenticated attributes (RFC 5652 §5.4). The oidDigestAlg parameter specifies which hash algorithm to use, matching the signer's digestAlgorithm.
err := pkcs7.VerifyMessageDigestEmbedded(
signer.DigestAlgorithm.Algorithm, expectedDigest, content)
func VerifyMessageDigestTSToken ¶
func VerifyMessageDigestTSToken(oidHashAlg asn1.ObjectIdentifier, digest, signedData []byte) error
VerifyMessageDigestTSToken verifies a message digest for timestamp token responses (RFC 3161). Delegates to VerifyMessageDigestEmbedded.
Types ¶
type Attribute ¶
type Attribute struct {
Type asn1.ObjectIdentifier
Value interface{}
}
Attribute represents a CMS attribute (RFC 5652 §11). Value must be marshalable by encoding/asn1.
type ESSCertID ¶
type ESSCertID struct {
CertHash []byte
IssuerAndSerialNumber issuerAndSerial `asn1:"optional"`
}
ESSCertID identifies a certificate by hash for the id-smime-aa-signingCertificate attribute (RFC 2634 §5.4).
type ESSCertIDv2 ¶
type ESSCertIDv2 struct {
HashAlgorithm pkix.AlgorithmIdentifier `asn1:"optional"` // DEFAULT sha256
CertHash []byte
IssuerAndSerialNumber issuerAndSerial `asn1:"optional"`
}
ESSCertIDv2 identifies a certificate by hash for the id-smime-aa-signingCertificateV2 attribute (RFC 5035 §3). HashAlgorithm defaults to SHA-256 when absent.
type MessageDigestMismatchError ¶
MessageDigestMismatchError indicates that the message-digest attribute in the SignerInfo does not match the independently computed digest of the content (RFC 5652 §5.4). This typically means the content was modified after signing.
func (*MessageDigestMismatchError) Error ¶
func (err *MessageDigestMismatchError) Error() string
type PKCS7 ¶
type PKCS7 struct {
Content []byte
ContentType asn1.ObjectIdentifier
Certificates []*x509.Certificate
CRLs []*x509.RevocationList
Signers []SignerInfo
// contains filtered or unexported fields
}
PKCS7 represents a parsed PKCS#7 / CMS message (RFC 5652 §3 ContentInfo). After calling Parse, the Content, Certificates, and Signers fields are populated from the inner structure. For EnvelopedData and EncryptedData, call PKCS7.Decrypt or PKCS7.DecryptUsingPSK to recover plaintext.
func Parse ¶
Parse decodes a DER or BER encoded PKCS#7 / CMS ContentInfo structure (RFC 5652 §3). BER input is automatically converted to DER before parsing.
The returned PKCS7 contains the parsed content, certificates, and signer information. For SignedData, call PKCS7.Verify to verify signatures. For EnvelopedData, call PKCS7.Decrypt to recover plaintext.
p7, err := pkcs7.Parse(derBytes)
if err != nil {
log.Fatal(err)
}
if err := p7.Verify(); err != nil {
log.Fatal(err)
}
fmt.Println(string(p7.Content))
func (*PKCS7) Decrypt ¶
func (p7 *PKCS7) Decrypt(cert *x509.Certificate, pkey crypto.PrivateKey) ([]byte, error)
Decrypt decrypts a CMS EnvelopedData structure (RFC 5652 §6). The recipient's certificate is used to find the matching RecipientInfo, and the private key decrypts the content-encryption key via RSA PKCS#1 v1.5.
p7, _ := pkcs7.Parse(envelopedDER) plaintext, err := p7.Decrypt(recipientCert, recipientKey)
TODO: Only RSA key transport is supported. ECDH key agreement (RFC 5652 §6.2.2) is not implemented.
func (*PKCS7) DecryptUsingPSK ¶
DecryptUsingPSK decrypts a CMS EncryptedData structure (RFC 5652 §8) using a pre-shared symmetric key.
p7, _ := pkcs7.Parse(encryptedDER) plaintext, err := p7.DecryptUsingPSK(symmetricKey)
func (*PKCS7) GetOnlySigner ¶
func (p7 *PKCS7) GetOnlySigner() *x509.Certificate
GetOnlySigner returns the certificate for the single signer of a SignedData. Returns nil if there are zero or more than one signers.
cert := p7.GetOnlySigner()
if cert == nil {
log.Fatal("expected exactly one signer")
}
func (*PKCS7) UnmarshalSignedAttribute ¶
func (p7 *PKCS7) UnmarshalSignedAttribute(attributeType asn1.ObjectIdentifier, out interface{}) error
UnmarshalSignedAttribute decodes a signed attribute from the first signer's authenticated attributes (RFC 5652 §11). The out parameter must be a pointer to a type compatible with encoding/asn1 unmarshaling.
var signingTime time.Time err := p7.UnmarshalSignedAttribute(pkcs7.OIDAttributeSigningTime, &signingTime)
func (*PKCS7) Verify ¶
Verify checks the signatures of a PKCS#7 SignedData structure (RFC 5652 §5.6) without certificate chain verification.
For each signer, it independently computes the message digest, validates the content-type attribute, and verifies the signature.
p7, _ := pkcs7.Parse(data)
if err := p7.Verify(); err != nil {
log.Fatal("signature verification failed:", err)
}
func (*PKCS7) VerifyWithChain ¶
VerifyWithChain checks the signatures and certificate chains of a PKCS#7 SignedData (RFC 5652 §5.6). If truststore is non-nil, each signer's certificate chain is verified to a root in the trust store. Chain validation time uses the signing-time attribute if present, otherwise the current time.
roots := x509.NewCertPool()
roots.AppendCertsFromPEM(rootPEM)
if err := p7.VerifyWithChain(roots); err != nil {
log.Fatal(err)
}
func (*PKCS7) VerifyWithChainAtTime ¶
func (p7 *PKCS7) VerifyWithChainAtTime(truststore *x509.CertPool, currentTime time.Time) (err error)
VerifyWithChainAtTime checks signatures and certificate chains at a specific time, ignoring the signing-time attribute. Use this when you need to verify a signature as it was valid at a particular point in time.
validAt := time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)
if err := p7.VerifyWithChainAtTime(roots, validAt); err != nil {
log.Fatal(err)
}
type SignedData ¶
type SignedData struct {
// contains filtered or unexported fields
}
SignedData is a builder for creating CMS SignedData structures (RFC 5652 §5). Create one with NewSignedData, add signers with SignedData.AddSigner or SignedData.AddSignerChain, then call SignedData.Finish to produce the DER-encoded output.
Example ¶
// generate a signing cert or load a key pair
cert, err := createTestCertificate(x509.SHA256WithRSA)
if err != nil {
fmt.Printf("Cannot create test certificates: %s", err)
}
// Initialize a SignedData struct with content to be signed
signedData, err := NewSignedData()
//signedData, err := NewSignedData([]byte("Example data to be signed"))
if err != nil {
fmt.Printf("Cannot initialize signed data: %s", err)
}
// Add the signing cert and private key
if err := signedData.AddSigner(cert.Certificate, cert.PrivateKey, nil, nil, SignerInfoConfig{}); err != nil {
fmt.Printf("Cannot add signer: %s", err)
}
// Call Detach() is you want to remove content from the signature
// and generate an S/MIME detached signature
//signedData.Detach()
// Finish() to obtain the signature bytes
detachedSignature, err := signedData.Finish()
if err != nil {
fmt.Printf("Cannot finish signing data: %s", err)
}
_ = pem.Encode(os.Stdout, &pem.Block{Type: "PKCS7", Bytes: detachedSignature})
func NewSignedData ¶
func NewSignedData() (*SignedData, error)
NewSignedData initializes a CMS SignedData builder (RFC 5652 §5.1). The returned SignedData is ready for adding signers via SignedData.AddSigner.
sd, err := pkcs7.NewSignedData()
if err != nil {
log.Fatal(err)
}
sd.SetContent([]byte("data to sign"))
err = sd.AddSigner(cert, key, nil, nil, pkcs7.SignerInfoConfig{})
der, err := sd.Finish()
func (*SignedData) AddCertificate ¶
func (sd *SignedData) AddCertificate(cert *x509.Certificate)
AddCertificate adds a certificate to the SignedData certificates field (RFC 5652 §5.1). Use this to include intermediate CA certificates.
func (*SignedData) AddSigner ¶
func (sd *SignedData) AddSigner(cert *x509.Certificate, pkey crypto.PrivateKey, messageDigest []byte, digestOid asn1.ObjectIdentifier, config SignerInfoConfig) error
AddSigner adds a signer to the SignedData without intermediate certificates. It is a convenience wrapper around SignedData.AddSignerChain.
If messageDigest is nil, it is computed over the encapsulated content. If digestOid is nil, it is inferred from the certificate's signature algorithm.
func (*SignedData) AddSignerChain ¶
func (sd *SignedData) AddSignerChain(cert *x509.Certificate, pkey crypto.PrivateKey, messageDigest []byte, digestOid asn1.ObjectIdentifier, parents []*x509.Certificate, config SignerInfoConfig) error
AddSignerChain creates a SignerInfo (RFC 5652 §5.3) and adds it to the SignedData along with the signer certificate and any intermediate certificates.
If digestOid is nil, the digest algorithm is inferred from the signer certificate's signature algorithm. If messageDigest is nil, it is computed over the encapsulated content (which may be empty for detached signatures).
The authenticated attributes always include content-type and message-digest as required by RFC 5652 §5.3. Additional attributes can be provided via config.
The signature is computed over the DER-encoded authenticated attributes (RFC 5652 §5.4).
func (*SignedData) Detach ¶
func (sd *SignedData) Detach()
Detach removes the encapsulated content from the SignedData, producing a detached signature (RFC 5652 §5.2). The recipient must supply the content separately for verification. Call this after adding signers but before SignedData.Finish.
Note: the message digest is computed over the content at AddSigner time, so the digest is already embedded in the signed attributes.
func (*SignedData) Finish ¶
func (sd *SignedData) Finish() ([]byte, error)
Finish marshals the SignedData into a DER-encoded CMS ContentInfo (RFC 5652 §3). The output can be parsed back with Parse.
signedDER, err := sd.Finish()
func (*SignedData) GetSignedData ¶
func (sd *SignedData) GetSignedData() *signedData
GetSignedData returns the internal signedData structure for advanced manipulation before calling SignedData.Finish.
func (*SignedData) SetContent ¶
func (sd *SignedData) SetContent(data []byte)
SetContent sets the encapsulated content (eContent) that will be signed (RFC 5652 §5.2). Call this before SignedData.AddSigner to include content in the SignedData structure. If not called, the content is empty (suitable for detached signatures after calling SignedData.Detach).
sd, _ := pkcs7.NewSignedData()
sd.SetContent([]byte("data to sign"))
sd.AddSigner(cert, key, nil, nil, pkcs7.SignerInfoConfig{})
type SignerInfo ¶
type SignerInfo struct {
Version int `asn1:"default:1"`
IssuerAndSerialNumber issuerAndSerial
DigestAlgorithm pkix.AlgorithmIdentifier
AuthenticatedAttributes []attribute `asn1:"optional,omitempty,tag:0"` // RFC5652: signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL
DigestEncryptionAlgorithm pkix.AlgorithmIdentifier
EncryptedDigest []byte `asn1:"octet"`
UnauthenticatedAttributes []attribute `asn1:"optional,omitempty,tag:1"` // RFC5652: unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL
}
SignerInfo contains per-signer information (RFC 5652 §5.3).
type SignerInfoConfig ¶
type SignerInfoConfig struct {
ExtraSignedAttributes []Attribute
ExtraUnsignedAttributes []Attribute
}
SignerInfoConfig holds optional attributes to include when adding a signer. Extra attributes are added to the SignerInfo authenticated or unauthenticated attribute sets (RFC 5652 §5.3).
type SigningCertificate ¶
type SigningCertificate struct {
Certs []ESSCertID `asn1:"sequence"`
}
SigningCertificate is the value of the id-smime-aa-signingCertificate attribute (RFC 2634 §5.4). It binds a signer to a specific certificate.
type SigningCertificateV2 ¶
type SigningCertificateV2 struct {
Certs []ESSCertIDv2
}
SigningCertificateV2 is the value of the id-smime-aa-signingCertificateV2 attribute (RFC 5035 §3).