github.com/emmansun/gmsm@v0.29.1/pkcs7/sign.go (about)

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