1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package appmanifest
18
19 import (
20 "bytes"
21 "crypto"
22 "crypto/ecdsa"
23 "crypto/elliptic"
24 "crypto/rsa"
25 "encoding/binary"
26 "encoding/hex"
27 "errors"
28 "math/big"
29
30 "github.com/sassoftware/relic/lib/certloader"
31 "github.com/sassoftware/relic/lib/x509tools"
32 )
33
34 func PublisherIdentity(cert *certloader.Certificate) (string, string, error) {
35 issuer := cert.Issuer()
36 if issuer == nil {
37 return "", "", errors.New("unable to find issuer certificate in chain")
38 }
39 aki, err := x509tools.SubjectKeyID(issuer.PublicKey)
40 if err != nil {
41 return "", "", err
42 }
43 name := x509tools.FormatPkixName(cert.Leaf.RawSubject, x509tools.NameStyleMsOsco)
44 return name, hex.EncodeToString(aki), nil
45 }
46
47 const (
48 snkRsaPub = 0x06
49 snkRsaPriv = 0x07
50 snkRsaVersion = 0x02
51
52 calgRsaSign = 0x2400
53 calgSha1 = 0x8004
54 calgEcdsa = 0x2203
55
56 bcryptRsaPubMagic = 0x31415352
57 bcryptEcdsaPubP256 = 0x31534345
58 bcryptEcdsaPubP384 = 0x33534345
59 bcryptEcdsaPubP521 = 0x35534345
60 )
61
62 type snkHeader struct {
63 PubAlgorithm uint32
64 HashAlgorithm uint32
65 BlobSize uint32
66 KeyType uint8
67 Version uint8
68 Reserved uint16
69 PubAlgorithm2 uint32
70 }
71
72 type blobRsaPub struct {
73 snkHeader
74
75 KeyMagic uint32
76 BitLength uint32
77 PubExponent uint32
78 }
79
80 type blobEcdsaPub struct {
81 snkHeader
82
83 KeyMagic uint32
84 ByteLength uint32
85 }
86
87
88
89
90
91 func PublicKeyToken(pubKey crypto.PublicKey) (string, error) {
92 snk, err := PublicKeyToSnk(pubKey)
93 if err != nil {
94 return "", err
95 }
96 d := crypto.SHA1.New()
97 d.Write(snk)
98
99
100 sum := d.Sum(nil)
101 token := make([]byte, 8)
102 for i := 0; i < 8; i++ {
103 token[i] = sum[19-i]
104 }
105 return hex.EncodeToString(token), nil
106 }
107
108
109 func PublicKeyToSnk(pubKey crypto.PublicKey) ([]byte, error) {
110 var buf bytes.Buffer
111 switch k := pubKey.(type) {
112 case *rsa.PublicKey:
113 modulus := bigIntToLE(k.N)
114 if err := binary.Write(&buf, binary.LittleEndian, blobRsaPub{
115 snkHeader: snkHeader{
116 PubAlgorithm: calgRsaSign,
117 HashAlgorithm: calgSha1,
118 BlobSize: uint32(20 + len(modulus)),
119 KeyType: snkRsaPub,
120 Version: snkRsaVersion,
121 PubAlgorithm2: calgRsaSign,
122 },
123 KeyMagic: bcryptRsaPubMagic,
124 BitLength: uint32(8 * len(modulus)),
125 PubExponent: uint32(k.E),
126 }); err != nil {
127 return nil, nil
128 }
129 buf.Write(modulus)
130 case *ecdsa.PublicKey:
131
132
133
134
135
136 var keyMagic uint32
137 switch k.Curve {
138 case elliptic.P256():
139 keyMagic = bcryptEcdsaPubP256
140 case elliptic.P384():
141 keyMagic = bcryptEcdsaPubP384
142 case elliptic.P521():
143 keyMagic = bcryptEcdsaPubP521
144 default:
145 return nil, errors.New("unsupported ECDSA curve")
146 }
147
148
149
150 x := k.X.Bytes()
151 y := k.Y.Bytes()
152 if err := binary.Write(&buf, binary.LittleEndian, blobEcdsaPub{
153 snkHeader: snkHeader{
154 PubAlgorithm: calgEcdsa,
155 HashAlgorithm: calgSha1,
156 BlobSize: uint32(12 + 2*len(x)),
157 KeyType: snkRsaPub,
158 Version: snkRsaVersion,
159 PubAlgorithm2: calgEcdsa,
160 },
161 KeyMagic: keyMagic,
162 ByteLength: uint32(len(x)),
163 }); err != nil {
164 return nil, nil
165 }
166 buf.Write(x)
167 buf.Write(y)
168 default:
169 return nil, errors.New("unsupported key type for strong name signing")
170 }
171 return buf.Bytes(), nil
172 }
173
174 func bigIntToLE(x *big.Int) []byte {
175 b := x.Bytes()
176 for i := 0; i < len(b)/2; i++ {
177 j := len(b) - i - 1
178 b[i], b[j] = b[j], b[i]
179 }
180 return b
181 }
182
View as plain text