github.com/c-darwin/mobile@v0.0.0-20160313183840-ff625c46f7c9/cmd/gomobile/cert.go (about)

     1  // Copyright 2015 The Go Authors.  All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package main
     6  
     7  import (
     8  	"crypto"
     9  	"crypto/rsa"
    10  	"crypto/sha1"
    11  	"crypto/x509"
    12  	"crypto/x509/pkix"
    13  	"encoding/asn1"
    14  	"io"
    15  	"math/big"
    16  	"time"
    17  )
    18  
    19  // signPKCS7 does the minimal amount of work necessary to embed an RSA
    20  // signature into a PKCS#7 certificate.
    21  //
    22  // We prepare the certificate using the x509 package, read it back in
    23  // to our custom data type and then write it back out with the signature.
    24  func signPKCS7(rand io.Reader, priv *rsa.PrivateKey, msg []byte) ([]byte, error) {
    25  	const serialNumber = 0x5462c4dd // arbitrary
    26  	name := pkix.Name{CommonName: "gomobile"}
    27  
    28  	template := &x509.Certificate{
    29  		SerialNumber:       big.NewInt(serialNumber),
    30  		SignatureAlgorithm: x509.SHA1WithRSA,
    31  		Subject:            name,
    32  	}
    33  
    34  	b, err := x509.CreateCertificate(rand, template, template, priv.Public(), priv)
    35  	if err != nil {
    36  		return nil, err
    37  	}
    38  
    39  	c := certificate{}
    40  	if _, err := asn1.Unmarshal(b, &c); err != nil {
    41  		return nil, err
    42  	}
    43  
    44  	h := sha1.New()
    45  	h.Write(msg)
    46  	hashed := h.Sum(nil)
    47  
    48  	signed, err := rsa.SignPKCS1v15(rand, priv, crypto.SHA1, hashed)
    49  	if err != nil {
    50  		return nil, err
    51  	}
    52  
    53  	content := pkcs7SignedData{
    54  		ContentType: oidSignedData,
    55  		Content: signedData{
    56  			Version: 1,
    57  			DigestAlgorithms: []pkix.AlgorithmIdentifier{{
    58  				Algorithm:  oidSHA1,
    59  				Parameters: asn1.RawValue{Tag: 5},
    60  			}},
    61  			ContentInfo:  contentInfo{Type: oidData},
    62  			Certificates: c,
    63  			SignerInfos: []signerInfo{{
    64  				Version: 1,
    65  				IssuerAndSerialNumber: issuerAndSerialNumber{
    66  					Issuer:       name.ToRDNSequence(),
    67  					SerialNumber: serialNumber,
    68  				},
    69  				DigestAlgorithm: pkix.AlgorithmIdentifier{
    70  					Algorithm:  oidSHA1,
    71  					Parameters: asn1.RawValue{Tag: 5},
    72  				},
    73  				DigestEncryptionAlgorithm: pkix.AlgorithmIdentifier{
    74  					Algorithm:  oidRSAEncryption,
    75  					Parameters: asn1.RawValue{Tag: 5},
    76  				},
    77  				EncryptedDigest: signed,
    78  			}},
    79  		},
    80  	}
    81  
    82  	return asn1.Marshal(content)
    83  }
    84  
    85  type pkcs7SignedData struct {
    86  	ContentType asn1.ObjectIdentifier
    87  	Content     signedData `asn1:"tag:0,explicit"`
    88  }
    89  
    90  // signedData is defined in rfc2315, section 9.1.
    91  type signedData struct {
    92  	Version          int
    93  	DigestAlgorithms []pkix.AlgorithmIdentifier `asn1:"set"`
    94  	ContentInfo      contentInfo
    95  	Certificates     certificate  `asn1:"tag0,explicit"`
    96  	SignerInfos      []signerInfo `asn1:"set"`
    97  }
    98  
    99  type contentInfo struct {
   100  	Type asn1.ObjectIdentifier
   101  	// Content is optional in PKCS#7 and not provided here.
   102  }
   103  
   104  // certificate is defined in rfc2459, section 4.1.
   105  type certificate struct {
   106  	TBSCertificate     tbsCertificate
   107  	SignatureAlgorithm pkix.AlgorithmIdentifier
   108  	SignatureValue     asn1.BitString
   109  }
   110  
   111  // tbsCertificate is defined in rfc2459, section 4.1.
   112  type tbsCertificate struct {
   113  	Version      int `asn1:"tag:0,default:2,explicit"`
   114  	SerialNumber int
   115  	Signature    pkix.AlgorithmIdentifier
   116  	Issuer       pkix.RDNSequence // pkix.Name
   117  	Validity     validity
   118  	Subject      pkix.RDNSequence // pkix.Name
   119  	SubjectPKI   subjectPublicKeyInfo
   120  }
   121  
   122  // validity is defined in rfc2459, section 4.1.
   123  type validity struct {
   124  	NotBefore time.Time
   125  	NotAfter  time.Time
   126  }
   127  
   128  // subjectPublicKeyInfo is defined in rfc2459, section 4.1.
   129  type subjectPublicKeyInfo struct {
   130  	Algorithm        pkix.AlgorithmIdentifier
   131  	SubjectPublicKey asn1.BitString
   132  }
   133  
   134  type signerInfo struct {
   135  	Version                   int
   136  	IssuerAndSerialNumber     issuerAndSerialNumber
   137  	DigestAlgorithm           pkix.AlgorithmIdentifier
   138  	DigestEncryptionAlgorithm pkix.AlgorithmIdentifier
   139  	EncryptedDigest           []byte
   140  }
   141  
   142  type issuerAndSerialNumber struct {
   143  	Issuer       pkix.RDNSequence // pkix.Name
   144  	SerialNumber int
   145  }
   146  
   147  // Various ASN.1 Object Identifies, mostly from rfc3852.
   148  var (
   149  	oidPKCS7         = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7}
   150  	oidData          = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 1}
   151  	oidSignedData    = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 7, 2}
   152  	oidSHA1          = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 26}
   153  	oidRSAEncryption = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
   154  )