...

Package pkcs7

import "github.com/digitorus/pkcs7"
Overview
Index
Examples

Overview ▾

Package pkcs7 implements parsing and generation of some PKCS#7 structures.

Index ▾

Constants
Variables
func DegenerateCertificate(cert []byte) ([]byte, error)
func Encrypt(content []byte, recipients []*x509.Certificate) ([]byte, error)
func EncryptUsingPSK(content []byte, key []byte) ([]byte, error)
func GetDigestOIDForSignatureAlgorithm(digestAlg x509.SignatureAlgorithm) (asn1.ObjectIdentifier, error)
func TestDSASignWithOpenSSLAndVerify(t *testing.T)
func TestVerifyEC2(t *testing.T)
type Attribute
type DSATestFixture
    func UnmarshalDSATestFixture(testPEMBlock string) DSATestFixture
type MessageDigestMismatchError
    func (err *MessageDigestMismatchError) Error() string
type PKCS7
    func Parse(data []byte) (p7 *PKCS7, err error)
    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)
    func (p7 *PKCS7) VerifyWithOpts(opts x509.VerifyOptions) (err error)
type SignedData
    func NewSignedData(data []byte) (*SignedData, error)
    func (sd *SignedData) AddCertificate(cert *x509.Certificate)
    func (sd *SignedData) AddSigner(ee *x509.Certificate, keyOrSigner interface{}, config SignerInfoConfig) error
    func (sd *SignedData) AddSignerChain(ee *x509.Certificate, keyOrSigner interface{}, parents []*x509.Certificate, config SignerInfoConfig) error
    func (sd *SignedData) Detach()
    func (sd *SignedData) Finish() ([]byte, error)
    func (sd *SignedData) GetSignedData() *signedData
    func (sd *SignedData) RemoveAuthenticatedAttributes()
    func (sd *SignedData) RemoveUnauthenticatedAttributes()
    func (sd *SignedData) SetContentType(contentType asn1.ObjectIdentifier)
    func (sd *SignedData) SetDigestAlgorithm(d asn1.ObjectIdentifier)
    func (sd *SignedData) SetEncryptionAlgorithm(d asn1.ObjectIdentifier)
    func (sd *SignedData) SignWithoutAttr(ee *x509.Certificate, keyOrSigner interface{}, config SignerInfoConfig) error
type SignerInfoConfig

Examples

SignedData

Package files

ber.go decrypt.go encrypt.go pkcs7.go sign.go verify.go verify_test_dsa.go

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 (
    // Signed Data OIDs
    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}
    OIDEncryptedData          = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 6}
    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}
    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}
    OIDEncryptionAlgorithmECDSAP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34}
    OIDEncryptionAlgorithmECDSAP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35}

    OIDEncryptionAlgorithmEDDSA25519 = asn1.ObjectIdentifier{1, 3, 101, 112}

    // Encryption Algorithms
    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}
)

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 ContentEncryptionAlgorithm = EncryptionAlgorithmDESCBC
var EC2IdentityDocumentFixture = `
-----BEGIN PKCS7-----
MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAaCA
JIAEggGmewogICJwcml2YXRlSXAiIDogIjE3Mi4zMC4wLjI1MiIsCiAgImRldnBh
eVByb2R1Y3RDb2RlcyIgOiBudWxsLAogICJhdmFpbGFiaWxpdHlab25lIiA6ICJ1
cy1lYXN0LTFhIiwKICAidmVyc2lvbiIgOiAiMjAxMC0wOC0zMSIsCiAgImluc3Rh
bmNlSWQiIDogImktZjc5ZmU1NmMiLAogICJiaWxsaW5nUHJvZHVjdHMiIDogbnVs
bCwKICAiaW5zdGFuY2VUeXBlIiA6ICJ0Mi5taWNybyIsCiAgImFjY291bnRJZCIg
OiAiMTIxNjU5MDE0MzM0IiwKICAiaW1hZ2VJZCIgOiAiYW1pLWZjZTNjNjk2IiwK
ICAicGVuZGluZ1RpbWUiIDogIjIwMTYtMDQtMDhUMDM6MDE6MzhaIiwKICAiYXJj
aGl0ZWN0dXJlIiA6ICJ4ODZfNjQiLAogICJrZXJuZWxJZCIgOiBudWxsLAogICJy
YW1kaXNrSWQiIDogbnVsbCwKICAicmVnaW9uIiA6ICJ1cy1lYXN0LTEiCn0AAAAA
AAAxggEYMIIBFAIBATBpMFwxCzAJBgNVBAYTAlVTMRkwFwYDVQQIExBXYXNoaW5n
dG9uIFN0YXRlMRAwDgYDVQQHEwdTZWF0dGxlMSAwHgYDVQQKExdBbWF6b24gV2Vi
IFNlcnZpY2VzIExMQwIJAJa6SNnlXhpnMAkGBSsOAwIaBQCgXTAYBgkqhkiG9w0B
CQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xNjA0MDgwMzAxNDRaMCMG
CSqGSIb3DQEJBDEWBBTuUc28eBXmImAautC+wOjqcFCBVjAJBgcqhkjOOAQDBC8w
LQIVAKA54NxGHWWCz5InboDmY/GHs33nAhQ6O/ZI86NwjA9Vz3RNMUJrUPU5tAAA
AAAAAA==
-----END PKCS7-----
-----BEGIN CERTIFICATE-----
MIIC7TCCAq0CCQCWukjZ5V4aZzAJBgcqhkjOOAQDMFwxCzAJBgNVBAYTAlVTMRkw
FwYDVQQIExBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHEwdTZWF0dGxlMSAwHgYD
VQQKExdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzAeFw0xMjAxMDUxMjU2MTJaFw0z
ODAxMDUxMjU2MTJaMFwxCzAJBgNVBAYTAlVTMRkwFwYDVQQIExBXYXNoaW5ndG9u
IFN0YXRlMRAwDgYDVQQHEwdTZWF0dGxlMSAwHgYDVQQKExdBbWF6b24gV2ViIFNl
cnZpY2VzIExMQzCCAbcwggEsBgcqhkjOOAQBMIIBHwKBgQCjkvcS2bb1VQ4yt/5e
ih5OO6kK/n1Lzllr7D8ZwtQP8fOEpp5E2ng+D6Ud1Z1gYipr58Kj3nssSNpI6bX3
VyIQzK7wLclnd/YozqNNmgIyZecN7EglK9ITHJLP+x8FtUpt3QbyYXJdmVMegN6P
hviYt5JH/nYl4hh3Pa1HJdskgQIVALVJ3ER11+Ko4tP6nwvHwh6+ERYRAoGBAI1j
k+tkqMVHuAFcvAGKocTgsjJem6/5qomzJuKDmbJNu9Qxw3rAotXau8Qe+MBcJl/U
hhy1KHVpCGl9fueQ2s6IL0CaO/buycU1CiYQk40KNHCcHfNiZbdlx1E9rpUp7bnF
lRa2v1ntMX3caRVDdbtPEWmdxSCYsYFDk4mZrOLBA4GEAAKBgEbmeve5f8LIE/Gf
MNmP9CM5eovQOGx5ho8WqD+aTebs+k2tn92BBPqeZqpWRa5P/+jrdKml1qx4llHW
MXrs3IgIb6+hUIB+S8dz8/mmO0bpr76RoZVCXYab2CZedFut7qc3WUH9+EUAH5mw
vSeDCOUMYQR7R9LINYwouHIziqQYMAkGByqGSM44BAMDLwAwLAIUWXBlk40xTwSw
7HX32MxXYruse9ACFBNGmdX2ZBrVNGrN9N2f6ROk0k9K
-----END CERTIFICATE-----`

ErrNotEncryptedContent is returned when attempting to Decrypt data that is not encrypted data

var ErrNotEncryptedContent = errors.New("pkcs7: content data is a decryptable data type")

ErrPSKNotProvided is returned when attempting to encrypt using a PSK without actually providing the PSK.

var ErrPSKNotProvided = errors.New("pkcs7: cannot encrypt content: PSK not provided")

ErrUnsupportedAlgorithm tells you when our quick dev assumptions have failed

var ErrUnsupportedAlgorithm = errors.New("pkcs7: cannot decrypt data: only RSA, DES, DES-EDE3, AES-256-CBC and AES-128-GCM supported")

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 ErrUnsupportedContentType = errors.New("pkcs7: cannot parse data: unimplemented content type")

ErrUnsupportedEncryptionAlgorithm is returned when attempting to encrypt content with an unsupported algorithm.

var ErrUnsupportedEncryptionAlgorithm = errors.New("pkcs7: cannot encrypt content: only DES-CBC, AES-CBC, and AES-GCM supported")

func DegenerateCertificate

func DegenerateCertificate(cert []byte) ([]byte, error)

DegenerateCertificate creates a signed data structure containing only the provided certificate or certificate chain.

func Encrypt

func Encrypt(content []byte, recipients []*x509.Certificate) ([]byte, error)

Encrypt creates and returns an envelope data PKCS7 structure with encrypted recipient keys for each recipient public key.

The algorithm used to perform encryption is determined by the current value of the global ContentEncryptionAlgorithm package variable. By default, the value is EncryptionAlgorithmDESCBC. To use a different algorithm, change the value before calling Encrypt(). For example:

ContentEncryptionAlgorithm = EncryptionAlgorithmAES128GCM

TODO(fullsailor): Add support for encrypting content with other algorithms

func EncryptUsingPSK

func EncryptUsingPSK(content []byte, key []byte) ([]byte, error)

EncryptUsingPSK creates and returns an encrypted data PKCS7 structure, encrypted using caller provided pre-shared secret.

func GetDigestOIDForSignatureAlgorithm

func GetDigestOIDForSignatureAlgorithm(digestAlg x509.SignatureAlgorithm) (asn1.ObjectIdentifier, error)

GetDigestOIDForSignatureAlgorithm takes an x509.SignatureAlgorithm and returns the corresponding OID digest algorithm

func TestDSASignWithOpenSSLAndVerify

func TestDSASignWithOpenSSLAndVerify(t *testing.T)

func TestVerifyEC2

func TestVerifyEC2(t *testing.T)

type Attribute

Attribute represents a key value pair attribute. Value must be marshalable byte `encoding/asn1`

type Attribute struct {
    Type  asn1.ObjectIdentifier
    Value interface{}
}

type DSATestFixture

type DSATestFixture struct {
    Input       []byte
    Certificate *x509.Certificate
}

func UnmarshalDSATestFixture

func UnmarshalDSATestFixture(testPEMBlock string) DSATestFixture

type MessageDigestMismatchError

MessageDigestMismatchError is returned when the signer data digest does not match the computed digest for the contained content

type MessageDigestMismatchError struct {
    ExpectedDigest []byte
    ActualDigest   []byte
}

func (*MessageDigestMismatchError) Error

func (err *MessageDigestMismatchError) Error() string

type PKCS7

PKCS7 Represents a PKCS7 structure

type PKCS7 struct {
    Content      []byte
    Certificates []*x509.Certificate
    CRLs         []pkix.CertificateList
    Signers      []signerInfo
    // contains filtered or unexported fields
}

func Parse

func Parse(data []byte) (p7 *PKCS7, err error)

Parse decodes a DER encoded PKCS7 package

func (*PKCS7) Decrypt

func (p7 *PKCS7) Decrypt(cert *x509.Certificate, pkey crypto.PrivateKey) ([]byte, error)

Decrypt decrypts encrypted content info for recipient cert and private key

func (*PKCS7) DecryptUsingPSK

func (p7 *PKCS7) DecryptUsingPSK(key []byte) ([]byte, error)

DecryptUsingPSK decrypts encrypted data using caller provided pre-shared secret

func (*PKCS7) GetOnlySigner

func (p7 *PKCS7) GetOnlySigner() *x509.Certificate

GetOnlySigner returns an x509.Certificate for the first signer of the signed data payload. If there are more or less than one signer, nil is returned

func (*PKCS7) UnmarshalSignedAttribute

func (p7 *PKCS7) UnmarshalSignedAttribute(attributeType asn1.ObjectIdentifier, out interface{}) error

UnmarshalSignedAttribute decodes a single attribute from the signer info

func (*PKCS7) Verify

func (p7 *PKCS7) Verify() (err error)

Verify is a wrapper around VerifyWithChain() that initializes an empty trust store, effectively disabling certificate verification when validating a signature.

func (*PKCS7) VerifyWithChain

func (p7 *PKCS7) VerifyWithChain(truststore *x509.CertPool) (err error)

VerifyWithChain checks the signatures of a PKCS7 object.

If truststore is not nil, it also verifies the chain of trust of the end-entity signer cert to one of the roots in the truststore. When the PKCS7 object includes the signing time authenticated attr it verifies the chain at that time and UTC now otherwise.

func (*PKCS7) VerifyWithChainAtTime

func (p7 *PKCS7) VerifyWithChainAtTime(truststore *x509.CertPool, currentTime time.Time) (err error)

VerifyWithChainAtTime checks the signatures of a PKCS7 object.

If truststore is not nil, it also verifies the chain of trust of the end-entity signer cert to a root in the truststore at currentTime. It does not use the signing time authenticated attribute.

func (*PKCS7) VerifyWithOpts

func (p7 *PKCS7) VerifyWithOpts(opts x509.VerifyOptions) (err error)

If VerifyOpts.Roots is not nil it verifies the chain of trust of the end-entity signer cert to one of the roots in the truststore. When the PKCS7 object includes the signing time authenticated attr it verifies the chain at that time and UTC now otherwise.

type SignedData

SignedData is an opaque data structure for creating signed data payloads

type SignedData struct {
    // contains filtered or unexported fields
}

Example

Code:

// 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([]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, 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
_, err = signedData.Finish()
if err != nil {
    fmt.Printf("Cannot finish signing data: %s", err)
}

func NewSignedData

func NewSignedData(data []byte) (*SignedData, error)

NewSignedData takes data and initializes a PKCS7 SignedData struct that is ready to be signed via AddSigner. The digest algorithm is set to SHA1 by default and can be changed by calling SetDigestAlgorithm.

func (*SignedData) AddCertificate

func (sd *SignedData) AddCertificate(cert *x509.Certificate)

AddCertificate adds the certificate to the payload. Useful for parent certificates

func (*SignedData) AddSigner

func (sd *SignedData) AddSigner(ee *x509.Certificate, keyOrSigner interface{}, config SignerInfoConfig) error

AddSigner is a wrapper around AddSignerChain() that adds a signer without any parent. The signer can either be a crypto.Signer or crypto.PrivateKey.

func (*SignedData) AddSignerChain

func (sd *SignedData) AddSignerChain(ee *x509.Certificate, keyOrSigner interface{}, parents []*x509.Certificate, config SignerInfoConfig) error

AddSignerChain signs attributes about the content and adds certificates and signers infos to the Signed Data. The certificate and private key of the end-entity signer are used to issue the signature, and any parent of that end-entity that need to be added to the list of certifications can be specified in the parents slice.

The signature algorithm used to hash the data is the one of the end-entity certificate. The signer can be either a crypto.Signer or crypto.PrivateKey.

func (*SignedData) Detach

func (sd *SignedData) Detach()

Detach removes content from the signed data struct to make it a detached signature. This must be called right before Finish()

func (*SignedData) Finish

func (sd *SignedData) Finish() ([]byte, error)

Finish marshals the content and its signers

func (*SignedData) GetSignedData

func (sd *SignedData) GetSignedData() *signedData

GetSignedData returns the private Signed Data

func (*SignedData) RemoveAuthenticatedAttributes

func (sd *SignedData) RemoveAuthenticatedAttributes()

RemoveAuthenticatedAttributes removes authenticated attributes from signedData similar to OpenSSL's PKCS7_NOATTR or -noattr flags

func (*SignedData) RemoveUnauthenticatedAttributes

func (sd *SignedData) RemoveUnauthenticatedAttributes()

RemoveUnauthenticatedAttributes removes unauthenticated attributes from signedData

func (*SignedData) SetContentType

func (sd *SignedData) SetContentType(contentType asn1.ObjectIdentifier)

SetContentType sets the content type of the SignedData. For example to specify the content type of a time-stamp token according to RFC 3161 section 2.4.2.

func (*SignedData) SetDigestAlgorithm

func (sd *SignedData) SetDigestAlgorithm(d asn1.ObjectIdentifier)

SetDigestAlgorithm sets the digest algorithm to be used in the signing process.

This should be called before adding signers

func (*SignedData) SetEncryptionAlgorithm

func (sd *SignedData) SetEncryptionAlgorithm(d asn1.ObjectIdentifier)

SetEncryptionAlgorithm sets the encryption algorithm to be used in the signing process.

This should be called before adding signers

func (*SignedData) SignWithoutAttr

func (sd *SignedData) SignWithoutAttr(ee *x509.Certificate, keyOrSigner interface{}, config SignerInfoConfig) error

SignWithoutAttr issues a signature on the content of the pkcs7 SignedData. Unlike AddSigner/AddSignerChain, it calculates the digest on the data alone and does not include any signed attributes like timestamp and so on.

This function is needed to sign old Android APKs, something you probably shouldn't do unless you're maintaining backward compatibility for old applications. The signer can be either a crypto.Signer or crypto.PrivateKey.

type SignerInfoConfig

SignerInfoConfig are optional values to include when adding a signer

type SignerInfoConfig struct {
    ExtraSignedAttributes   []Attribute
    ExtraUnsignedAttributes []Attribute
    SkipCertificates        bool
}