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 }