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 )