| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- // Copyright 2015 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package main
- import (
- "crypto"
- "crypto/rsa"
- "crypto/sha1"
- "crypto/x509"
- "crypto/x509/pkix"
- "encoding/asn1"
- "io"
- "math/big"
- "time"
- )
- // signPKCS7 does the minimal amount of work necessary to embed an RSA
- // signature into a PKCS#7 certificate.
- //
- // We prepare the certificate using the x509 package, read it back in
- // to our custom data type and then write it back out with the signature.
- func signPKCS7(rand io.Reader, priv *rsa.PrivateKey, msg []byte) ([]byte, error) {
- const serialNumber = 0x5462c4dd // arbitrary
- name := pkix.Name{CommonName: "gomobile"}
- template := &x509.Certificate{
- SerialNumber: big.NewInt(serialNumber),
- SignatureAlgorithm: x509.SHA1WithRSA,
- Subject: name,
- }
- b, err := x509.CreateCertificate(rand, template, template, priv.Public(), priv)
- if err != nil {
- return nil, err
- }
- c := certificate{}
- if _, err := asn1.Unmarshal(b, &c); err != nil {
- return nil, err
- }
- h := sha1.New()
- h.Write(msg)
- hashed := h.Sum(nil)
- signed, err := rsa.SignPKCS1v15(rand, priv, crypto.SHA1, hashed)
- if err != nil {
- return nil, err
- }
- content := pkcs7SignedData{
- ContentType: oidSignedData,
- Content: signedData{
- Version: 1,
- DigestAlgorithms: []pkix.AlgorithmIdentifier{{
- Algorithm: oidSHA1,
- Parameters: asn1.RawValue{Tag: 5},
- }},
- ContentInfo: contentInfo{Type: oidData},
- Certificates: c,
- SignerInfos: []signerInfo{{
- Version: 1,
- IssuerAndSerialNumber: issuerAndSerialNumber{
- Issuer: name.ToRDNSequence(),
- SerialNumber: serialNumber,
- },
- DigestAlgorithm: pkix.AlgorithmIdentifier{
- Algorithm: oidSHA1,
- Parameters: asn1.RawValue{Tag: 5},
- },
- DigestEncryptionAlgorithm: pkix.AlgorithmIdentifier{
- Algorithm: oidRSAEncryption,
- Parameters: asn1.RawValue{Tag: 5},
- },
- EncryptedDigest: signed,
- }},
- },
- }
- return asn1.Marshal(content)
- }
- type pkcs7SignedData struct {
- ContentType asn1.ObjectIdentifier
- Content signedData `asn1:"tag:0,explicit"`
- }
- // signedData is defined in rfc2315, section 9.1.
- type signedData struct {
- Version int
- DigestAlgorithms []pkix.AlgorithmIdentifier `asn1:"set"`
- ContentInfo contentInfo
- Certificates certificate `asn1:"tag0,explicit"`
- SignerInfos []signerInfo `asn1:"set"`
- }
- type contentInfo struct {
- Type asn1.ObjectIdentifier
- // Content is optional in PKCS#7 and not provided here.
- }
- // certificate is defined in rfc2459, section 4.1.
- type certificate struct {
- TBSCertificate tbsCertificate
- SignatureAlgorithm pkix.AlgorithmIdentifier
- SignatureValue asn1.BitString
- }
- // tbsCertificate is defined in rfc2459, section 4.1.
- type tbsCertificate struct {
- Version int `asn1:"tag:0,default:2,explicit"`
- SerialNumber int
- Signature pkix.AlgorithmIdentifier
- Issuer pkix.RDNSequence // pkix.Name
- Validity validity
- Subject pkix.RDNSequence // pkix.Name
- SubjectPKI subjectPublicKeyInfo
- }
- // validity is defined in rfc2459, section 4.1.
- type validity struct {
- NotBefore time.Time
- NotAfter time.Time
- }
- // subjectPublicKeyInfo is defined in rfc2459, section 4.1.
- type subjectPublicKeyInfo struct {
- Algorithm pkix.AlgorithmIdentifier
- SubjectPublicKey asn1.BitString
- }
- type signerInfo struct {
- Version int
- IssuerAndSerialNumber issuerAndSerialNumber
- DigestAlgorithm pkix.AlgorithmIdentifier
- DigestEncryptionAlgorithm pkix.AlgorithmIdentifier
- EncryptedDigest []byte
- }
- type issuerAndSerialNumber struct {
- Issuer pkix.RDNSequence // pkix.Name
- SerialNumber int
- }
- // Various ASN.1 Object Identifies, mostly from rfc3852.
- var (
- oidPKCS7 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7}
- oidData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 1}
- oidSignedData = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 2}
- oidSHA1 = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 26}
- oidRSAEncryption = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
- )
|