README

pkcs7

GoDoc Build Status

pkcs7 implements parsing and creating signed and enveloped messages.

package main

import (
	"bytes"
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"os"

    "go.mozilla.org/pkcs7"
)

func SignAndDetach(content []byte, cert *x509.Certificate, privkey *rsa.PrivateKey) (signed []byte, err error) {
	toBeSigned, err := NewSignedData(content)
	if err != nil {
		err = fmt.Errorf("Cannot initialize signed data: %s", err)
		return
	}
	if err = toBeSigned.AddSigner(cert, privkey, SignerInfoConfig{}); err != nil {
		err = fmt.Errorf("Cannot add signer: %s", err)
		return
	}

	// Detach signature, omit if you want an embedded signature
	toBeSigned.Detach()

	signed, err = toBeSigned.Finish()
	if err != nil {
		err = fmt.Errorf("Cannot finish signing data: %s", err)
		return
	}

	// Verify the signature
	pem.Encode(os.Stdout, &pem.Block{Type: "PKCS7", Bytes: signed})
	p7, err := pkcs7.Parse(signed)
	if err != nil {
		err = fmt.Errorf("Cannot parse our signed data: %s", err)
		return
	}

	// since the signature was detached, reattach the content here
	p7.Content = content

	if bytes.Compare(content, p7.Content) != 0 {
		err = fmt.Errorf("Our content was not in the parsed data:\n\tExpected: %s\n\tActual: %s", content, p7.Content)
		return
	}
	if err = p7.Verify(); err != nil {
		err = fmt.Errorf("Cannot verify our signed data: %s", err)
		return
	}

	return signed, nil
}

Credits

This is a fork of fullsailor/pkcs7

Expand ▾ Collapse ▴

Documentation

Overview

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

    Index

    Examples

    Constants

    View Source
    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

    View Source
    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}
    
    	// 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}
    )
    View Source
    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.

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

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

        View Source
        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.

          View Source
          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

            View Source
            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)

              View Source
              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 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.

                      Types

                      type Attribute

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

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

                        type MessageDigestMismatchError

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

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

                          func (*MessageDigestMismatchError) Error

                          func (err *MessageDigestMismatchError) Error() string

                          type PKCS7

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

                            PKCS7 Represents a PKCS7 structure

                            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 root in the truststore.

                                          type SignedData

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

                                            SignedData is an opaque data structure for creating signed data payloads

                                            Example
                                            Output:
                                            
                                            

                                            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, pkey crypto.PrivateKey, config SignerInfoConfig) error

                                                  AddSigner is a wrapper around AddSignerChain() that adds a signer without any parent.

                                                  func (*SignedData) AddSignerChain

                                                  func (sd *SignedData) AddSignerChain(ee *x509.Certificate, pkey crypto.PrivateKey, 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.

                                                    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) 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, pkey crypto.PrivateKey, 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.

                                                                    type SignerInfoConfig

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

                                                                      SignerInfoConfig are optional values to include when adding a signer