...

Source file src/github.com/digitorus/pkcs7/sign.go

Documentation: github.com/digitorus/pkcs7

     1  package pkcs7
     2  
     3  import (
     4  	"bytes"
     5  	"crypto"
     6  	"crypto/dsa"
     7  	"crypto/ed25519"
     8  	"crypto/rand"
     9  	"crypto/x509"
    10  	"crypto/x509/pkix"
    11  	"encoding/asn1"
    12  	"errors"
    13  	"fmt"
    14  	"math/big"
    15  	"time"
    16  )
    17  
    18  // SignedData is an opaque data structure for creating signed data payloads
    19  type SignedData struct {
    20  	sd                  signedData
    21  	certs               []*x509.Certificate
    22  	data, messageDigest []byte
    23  	digestOid           asn1.ObjectIdentifier
    24  	encryptionOid       asn1.ObjectIdentifier
    25  }
    26  
    27  // NewSignedData takes data and initializes a PKCS7 SignedData struct that is
    28  // ready to be signed via AddSigner. The digest algorithm is set to SHA1 by default
    29  // and can be changed by calling SetDigestAlgorithm.
    30  func NewSignedData(data []byte) (*SignedData, error) {
    31  	content, err := asn1.Marshal(data)
    32  	if err != nil {
    33  		return nil, err
    34  	}
    35  	ci := contentInfo{
    36  		ContentType: OIDData,
    37  		Content:     asn1.RawValue{Class: 2, Tag: 0, Bytes: content, IsCompound: true},
    38  	}
    39  	sd := signedData{
    40  		ContentInfo: ci,
    41  		Version:     1,
    42  	}
    43  	return &SignedData{sd: sd, data: data, digestOid: OIDDigestAlgorithmSHA1}, nil
    44  }
    45  
    46  // SignerInfoConfig are optional values to include when adding a signer
    47  type SignerInfoConfig struct {
    48  	ExtraSignedAttributes   []Attribute
    49  	ExtraUnsignedAttributes []Attribute
    50  	SkipCertificates        bool
    51  }
    52  
    53  type signedData struct {
    54  	Version                    int                        `asn1:"default:1"`
    55  	DigestAlgorithmIdentifiers []pkix.AlgorithmIdentifier `asn1:"set"`
    56  	ContentInfo                contentInfo
    57  	Certificates               rawCertificates        `asn1:"optional,tag:0"`
    58  	CRLs                       []pkix.CertificateList `asn1:"optional,tag:1"`
    59  	SignerInfos                []signerInfo           `asn1:"set"`
    60  }
    61  
    62  type signerInfo struct {
    63  	Version                   int `asn1:"default:1"`
    64  	IssuerAndSerialNumber     issuerAndSerial
    65  	DigestAlgorithm           pkix.AlgorithmIdentifier
    66  	AuthenticatedAttributes   []attribute `asn1:"optional,omitempty,tag:0"`
    67  	DigestEncryptionAlgorithm pkix.AlgorithmIdentifier
    68  	EncryptedDigest           []byte
    69  	UnauthenticatedAttributes []attribute `asn1:"optional,omitempty,tag:1"`
    70  }
    71  
    72  type attribute struct {
    73  	Type  asn1.ObjectIdentifier
    74  	Value asn1.RawValue `asn1:"set"`
    75  }
    76  
    77  func marshalAttributes(attrs []attribute) ([]byte, error) {
    78  	encodedAttributes, err := asn1.Marshal(struct {
    79  		A []attribute `asn1:"set"`
    80  	}{A: attrs})
    81  	if err != nil {
    82  		return nil, err
    83  	}
    84  
    85  	// Remove the leading sequence octets
    86  	var raw asn1.RawValue
    87  	asn1.Unmarshal(encodedAttributes, &raw)
    88  	return raw.Bytes, nil
    89  }
    90  
    91  type rawCertificates struct {
    92  	Raw asn1.RawContent
    93  }
    94  
    95  type issuerAndSerial struct {
    96  	IssuerName   asn1.RawValue
    97  	SerialNumber *big.Int
    98  }
    99  
   100  // SetDigestAlgorithm sets the digest algorithm to be used in the signing process.
   101  //
   102  // This should be called before adding signers
   103  func (sd *SignedData) SetDigestAlgorithm(d asn1.ObjectIdentifier) {
   104  	sd.digestOid = d
   105  }
   106  
   107  // SetEncryptionAlgorithm sets the encryption algorithm to be used in the signing process.
   108  //
   109  // This should be called before adding signers
   110  func (sd *SignedData) SetEncryptionAlgorithm(d asn1.ObjectIdentifier) {
   111  	sd.encryptionOid = d
   112  }
   113  
   114  // AddSigner is a wrapper around AddSignerChain() that adds a signer without any parent. The signer can
   115  // either be a crypto.Signer or crypto.PrivateKey.
   116  func (sd *SignedData) AddSigner(ee *x509.Certificate, keyOrSigner interface{}, config SignerInfoConfig) error {
   117  	var parents []*x509.Certificate
   118  	return sd.AddSignerChain(ee, keyOrSigner, parents, config)
   119  }
   120  
   121  // AddSignerChain signs attributes about the content and adds certificates
   122  // and signers infos to the Signed Data. The certificate and private key
   123  // of the end-entity signer are used to issue the signature, and any
   124  // parent of that end-entity that need to be added to the list of
   125  // certifications can be specified in the parents slice.
   126  //
   127  // The signature algorithm used to hash the data is the one of the end-entity
   128  // certificate. The signer can be either a crypto.Signer or crypto.PrivateKey.
   129  func (sd *SignedData) AddSignerChain(ee *x509.Certificate, keyOrSigner interface{}, parents []*x509.Certificate, config SignerInfoConfig) error {
   130  	// Following RFC 2315, 9.2 SignerInfo type, the distinguished name of
   131  	// the issuer of the end-entity signer is stored in the issuerAndSerialNumber
   132  	// section of the SignedData.SignerInfo, alongside the serial number of
   133  	// the end-entity.
   134  	var ias issuerAndSerial
   135  	ias.SerialNumber = ee.SerialNumber
   136  	if len(parents) == 0 {
   137  		// no parent, the issuer is the end-entity cert itself
   138  		ias.IssuerName = asn1.RawValue{FullBytes: ee.RawIssuer}
   139  	} else {
   140  		err := verifyPartialChain(ee, parents)
   141  		if err != nil {
   142  			return err
   143  		}
   144  		// the first parent is the issuer
   145  		ias.IssuerName = asn1.RawValue{FullBytes: parents[0].RawSubject}
   146  	}
   147  	sd.sd.DigestAlgorithmIdentifiers = append(sd.sd.DigestAlgorithmIdentifiers,
   148  		pkix.AlgorithmIdentifier{Algorithm: sd.digestOid},
   149  	)
   150  	hash, err := getHashForOID(sd.digestOid)
   151  	if err != nil {
   152  		return err
   153  	}
   154  	h := hash.New()
   155  	h.Write(sd.data)
   156  	sd.messageDigest = h.Sum(nil)
   157  	encryptionOid, err := getOIDForEncryptionAlgorithm(keyOrSigner, sd.digestOid)
   158  	if err != nil {
   159  		return err
   160  	}
   161  	attrs := &attributes{}
   162  	attrs.Add(OIDAttributeContentType, sd.sd.ContentInfo.ContentType)
   163  	attrs.Add(OIDAttributeMessageDigest, sd.messageDigest)
   164  	attrs.Add(OIDAttributeSigningTime, time.Now().UTC())
   165  	for _, attr := range config.ExtraSignedAttributes {
   166  		attrs.Add(attr.Type, attr.Value)
   167  	}
   168  	finalAttrs, err := attrs.ForMarshalling()
   169  	if err != nil {
   170  		return err
   171  	}
   172  	unsignedAttrs := &attributes{}
   173  	for _, attr := range config.ExtraUnsignedAttributes {
   174  		unsignedAttrs.Add(attr.Type, attr.Value)
   175  	}
   176  	finalUnsignedAttrs, err := unsignedAttrs.ForMarshalling()
   177  	if err != nil {
   178  		return err
   179  	}
   180  	// create signature of signed attributes
   181  	signature, err := signAttributes(finalAttrs, keyOrSigner, hash)
   182  	if err != nil {
   183  		return err
   184  	}
   185  	signerInfo := signerInfo{
   186  		AuthenticatedAttributes:   finalAttrs,
   187  		UnauthenticatedAttributes: finalUnsignedAttrs,
   188  		DigestAlgorithm:           pkix.AlgorithmIdentifier{Algorithm: sd.digestOid},
   189  		DigestEncryptionAlgorithm: pkix.AlgorithmIdentifier{Algorithm: encryptionOid},
   190  		IssuerAndSerialNumber:     ias,
   191  		EncryptedDigest:           signature,
   192  		Version:                   1,
   193  	}
   194  	if !config.SkipCertificates {
   195  		sd.certs = append(sd.certs, ee)
   196  		if len(parents) > 0 {
   197  			sd.certs = append(sd.certs, parents...)
   198  		}
   199  	}
   200  	sd.sd.SignerInfos = append(sd.sd.SignerInfos, signerInfo)
   201  	return nil
   202  }
   203  
   204  // SignWithoutAttr issues a signature on the content of the pkcs7 SignedData.
   205  // Unlike AddSigner/AddSignerChain, it calculates the digest on the data alone
   206  // and does not include any signed attributes like timestamp and so on.
   207  //
   208  // This function is needed to sign old Android APKs, something you probably
   209  // shouldn't do unless you're maintaining backward compatibility for old
   210  // applications. The signer can be either a crypto.Signer or crypto.PrivateKey.
   211  func (sd *SignedData) SignWithoutAttr(ee *x509.Certificate, keyOrSigner interface{}, config SignerInfoConfig) error {
   212  	var signature []byte
   213  	sd.sd.DigestAlgorithmIdentifiers = append(sd.sd.DigestAlgorithmIdentifiers, pkix.AlgorithmIdentifier{Algorithm: sd.digestOid})
   214  	hash, err := getHashForOID(sd.digestOid)
   215  	if err != nil {
   216  		return err
   217  	}
   218  	h := hash.New()
   219  	h.Write(sd.data)
   220  	sd.messageDigest = h.Sum(nil)
   221  
   222  	switch pkey := keyOrSigner.(type) {
   223  	case *dsa.PrivateKey:
   224  		// dsa doesn't implement crypto.Signer so we make a special case
   225  		// https://github.com/golang/go/issues/27889
   226  		r, s, err := dsa.Sign(rand.Reader, pkey, sd.messageDigest)
   227  		if err != nil {
   228  			return err
   229  		}
   230  		signature, err = asn1.Marshal(dsaSignature{r, s})
   231  		if err != nil {
   232  			return err
   233  		}
   234  	default:
   235  		signer, ok := keyOrSigner.(crypto.Signer)
   236  		if !ok {
   237  			return errors.New("pkcs7: private key does not implement crypto.Signer")
   238  		}
   239  
   240  		// special case for Ed25519, which hashes as part of the signing algorithm
   241  		_, ok = signer.Public().(ed25519.PublicKey)
   242  		if ok {
   243  			signature, err = signer.Sign(rand.Reader, sd.data, crypto.Hash(0))
   244  		} else {
   245  			signature, err = signer.Sign(rand.Reader, sd.messageDigest, hash)
   246  			if err != nil {
   247  				return err
   248  			}
   249  		}
   250  	}
   251  
   252  	var ias issuerAndSerial
   253  	ias.SerialNumber = ee.SerialNumber
   254  	// no parent, the issue is the end-entity cert itself
   255  	ias.IssuerName = asn1.RawValue{FullBytes: ee.RawIssuer}
   256  	if sd.encryptionOid == nil {
   257  		// if the encryption algorithm wasn't set by SetEncryptionAlgorithm,
   258  		// infer it from the digest algorithm
   259  		sd.encryptionOid, err = getOIDForEncryptionAlgorithm(keyOrSigner, sd.digestOid)
   260  	}
   261  	if err != nil {
   262  		return err
   263  	}
   264  	signerInfo := signerInfo{
   265  		DigestAlgorithm:           pkix.AlgorithmIdentifier{Algorithm: sd.digestOid},
   266  		DigestEncryptionAlgorithm: pkix.AlgorithmIdentifier{Algorithm: sd.encryptionOid},
   267  		IssuerAndSerialNumber:     ias,
   268  		EncryptedDigest:           signature,
   269  		Version:                   1,
   270  	}
   271  	// create signature of signed attributes
   272  	sd.certs = append(sd.certs, ee)
   273  	sd.sd.SignerInfos = append(sd.sd.SignerInfos, signerInfo)
   274  	return nil
   275  }
   276  
   277  func (si *signerInfo) SetUnauthenticatedAttributes(extraUnsignedAttrs []Attribute) error {
   278  	unsignedAttrs := &attributes{}
   279  	for _, attr := range extraUnsignedAttrs {
   280  		unsignedAttrs.Add(attr.Type, attr.Value)
   281  	}
   282  	finalUnsignedAttrs, err := unsignedAttrs.ForMarshalling()
   283  	if err != nil {
   284  		return err
   285  	}
   286  
   287  	si.UnauthenticatedAttributes = finalUnsignedAttrs
   288  
   289  	return nil
   290  }
   291  
   292  // AddCertificate adds the certificate to the payload. Useful for parent certificates
   293  func (sd *SignedData) AddCertificate(cert *x509.Certificate) {
   294  	sd.certs = append(sd.certs, cert)
   295  }
   296  
   297  // SetContentType sets the content type of the SignedData. For example to specify the
   298  // content type of a time-stamp token according to RFC 3161 section 2.4.2.
   299  func (sd *SignedData) SetContentType(contentType asn1.ObjectIdentifier) {
   300  	sd.sd.ContentInfo.ContentType = contentType
   301  }
   302  
   303  // Detach removes content from the signed data struct to make it a detached signature.
   304  // This must be called right before Finish()
   305  func (sd *SignedData) Detach() {
   306  	sd.sd.ContentInfo = contentInfo{ContentType: OIDData}
   307  }
   308  
   309  // GetSignedData returns the private Signed Data
   310  func (sd *SignedData) GetSignedData() *signedData {
   311  	return &sd.sd
   312  }
   313  
   314  // Finish marshals the content and its signers
   315  func (sd *SignedData) Finish() ([]byte, error) {
   316  	sd.sd.Certificates = marshalCertificates(sd.certs)
   317  	inner, err := asn1.Marshal(sd.sd)
   318  	if err != nil {
   319  		return nil, err
   320  	}
   321  	outer := contentInfo{
   322  		ContentType: OIDSignedData,
   323  		Content:     asn1.RawValue{Class: 2, Tag: 0, Bytes: inner, IsCompound: true},
   324  	}
   325  	return asn1.Marshal(outer)
   326  }
   327  
   328  // RemoveAuthenticatedAttributes removes authenticated attributes from signedData
   329  // similar to OpenSSL's PKCS7_NOATTR or -noattr flags
   330  func (sd *SignedData) RemoveAuthenticatedAttributes() {
   331  	for i := range sd.sd.SignerInfos {
   332  		sd.sd.SignerInfos[i].AuthenticatedAttributes = nil
   333  	}
   334  }
   335  
   336  // RemoveUnauthenticatedAttributes removes unauthenticated attributes from signedData
   337  func (sd *SignedData) RemoveUnauthenticatedAttributes() {
   338  	for i := range sd.sd.SignerInfos {
   339  		sd.sd.SignerInfos[i].UnauthenticatedAttributes = nil
   340  	}
   341  }
   342  
   343  // verifyPartialChain checks that a given cert is issued by the first parent in the list,
   344  // then continue down the path. It doesn't require the last parent to be a root CA,
   345  // or to be trusted in any truststore. It simply verifies that the chain provided, albeit
   346  // partial, makes sense.
   347  func verifyPartialChain(cert *x509.Certificate, parents []*x509.Certificate) error {
   348  	if len(parents) == 0 {
   349  		return fmt.Errorf("pkcs7: zero parents provided to verify the signature of certificate %q", cert.Subject.CommonName)
   350  	}
   351  	err := cert.CheckSignatureFrom(parents[0])
   352  	if err != nil {
   353  		return fmt.Errorf("pkcs7: certificate signature from parent is invalid: %v", err)
   354  	}
   355  	if len(parents) == 1 {
   356  		// there is no more parent to check, return
   357  		return nil
   358  	}
   359  	return verifyPartialChain(parents[0], parents[1:])
   360  }
   361  
   362  func cert2issuerAndSerial(cert *x509.Certificate) (issuerAndSerial, error) {
   363  	var ias issuerAndSerial
   364  	// The issuer RDNSequence has to match exactly the sequence in the certificate
   365  	// We cannot use cert.Issuer.ToRDNSequence() here since it mangles the sequence
   366  	ias.IssuerName = asn1.RawValue{FullBytes: cert.RawIssuer}
   367  	ias.SerialNumber = cert.SerialNumber
   368  
   369  	return ias, nil
   370  }
   371  
   372  // signs the DER encoded form of the attributes with the private key
   373  func signAttributes(attrs []attribute, keyOrSigner interface{}, digestAlg crypto.Hash) ([]byte, error) {
   374  	attrBytes, err := marshalAttributes(attrs)
   375  	if err != nil {
   376  		return nil, err
   377  	}
   378  	h := digestAlg.New()
   379  	h.Write(attrBytes)
   380  	hash := h.Sum(nil)
   381  
   382  	// dsa doesn't implement crypto.Signer so we make a special case
   383  	// https://github.com/golang/go/issues/27889
   384  	switch pkey := keyOrSigner.(type) {
   385  	case *dsa.PrivateKey:
   386  		r, s, err := dsa.Sign(rand.Reader, pkey, hash)
   387  		if err != nil {
   388  			return nil, err
   389  		}
   390  		return asn1.Marshal(dsaSignature{r, s})
   391  	}
   392  
   393  	signer, ok := keyOrSigner.(crypto.Signer)
   394  	if !ok {
   395  		return nil, errors.New("pkcs7: private key does not implement crypto.Signer")
   396  	}
   397  
   398  	// special case for Ed25519, which hashes as part of the signing algorithm
   399  	_, ok = signer.Public().(ed25519.PublicKey)
   400  	if ok {
   401  		return signer.Sign(rand.Reader, attrBytes, crypto.Hash(0))
   402  	}
   403  
   404  	return signer.Sign(rand.Reader, hash, digestAlg)
   405  }
   406  
   407  type dsaSignature struct {
   408  	R, S *big.Int
   409  }
   410  
   411  // concats and wraps the certificates in the RawValue structure
   412  func marshalCertificates(certs []*x509.Certificate) rawCertificates {
   413  	var buf bytes.Buffer
   414  	for _, cert := range certs {
   415  		buf.Write(cert.Raw)
   416  	}
   417  	rawCerts, _ := marshalCertificateBytes(buf.Bytes())
   418  	return rawCerts
   419  }
   420  
   421  // Even though, the tag & length are stripped out during marshalling the
   422  // RawContent, we have to encode it into the RawContent. If its missing,
   423  // then `asn1.Marshal()` will strip out the certificate wrapper instead.
   424  func marshalCertificateBytes(certs []byte) (rawCertificates, error) {
   425  	var val = asn1.RawValue{Bytes: certs, Class: 2, Tag: 0, IsCompound: true}
   426  	b, err := asn1.Marshal(val)
   427  	if err != nil {
   428  		return rawCertificates{}, err
   429  	}
   430  	return rawCertificates{Raw: b}, nil
   431  }
   432  
   433  // DegenerateCertificate creates a signed data structure containing only the
   434  // provided certificate or certificate chain.
   435  func DegenerateCertificate(cert []byte) ([]byte, error) {
   436  	rawCert, err := marshalCertificateBytes(cert)
   437  	if err != nil {
   438  		return nil, err
   439  	}
   440  	emptyContent := contentInfo{ContentType: OIDData}
   441  	sd := signedData{
   442  		Version:      1,
   443  		ContentInfo:  emptyContent,
   444  		Certificates: rawCert,
   445  		CRLs:         []pkix.CertificateList{},
   446  	}
   447  	content, err := asn1.Marshal(sd)
   448  	if err != nil {
   449  		return nil, err
   450  	}
   451  	signedContent := contentInfo{
   452  		ContentType: OIDSignedData,
   453  		Content:     asn1.RawValue{Class: 2, Tag: 0, Bytes: content, IsCompound: true},
   454  	}
   455  	return asn1.Marshal(signedContent)
   456  }
   457  

View as plain text