]>
Commit | Line | Data |
---|---|---|
c680a8e1 RS |
1 | // Copyright 2013 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 packet | |
6 | ||
7 | import ( | |
8 | "crypto" | |
9 | "crypto/md5" | |
10 | "crypto/rsa" | |
11 | "encoding/binary" | |
12 | "fmt" | |
13 | "hash" | |
14 | "io" | |
15 | "math/big" | |
16 | "strconv" | |
17 | "time" | |
18 | ||
19 | "golang.org/x/crypto/openpgp/errors" | |
20 | ) | |
21 | ||
22 | // PublicKeyV3 represents older, version 3 public keys. These keys are less secure and | |
23 | // should not be used for signing or encrypting. They are supported here only for | |
24 | // parsing version 3 key material and validating signatures. | |
25 | // See RFC 4880, section 5.5.2. | |
26 | type PublicKeyV3 struct { | |
27 | CreationTime time.Time | |
28 | DaysToExpire uint16 | |
29 | PubKeyAlgo PublicKeyAlgorithm | |
30 | PublicKey *rsa.PublicKey | |
31 | Fingerprint [16]byte | |
32 | KeyId uint64 | |
33 | IsSubkey bool | |
34 | ||
35 | n, e parsedMPI | |
36 | } | |
37 | ||
38 | // newRSAPublicKeyV3 returns a PublicKey that wraps the given rsa.PublicKey. | |
39 | // Included here for testing purposes only. RFC 4880, section 5.5.2: | |
40 | // "an implementation MUST NOT generate a V3 key, but MAY accept it." | |
41 | func newRSAPublicKeyV3(creationTime time.Time, pub *rsa.PublicKey) *PublicKeyV3 { | |
42 | pk := &PublicKeyV3{ | |
43 | CreationTime: creationTime, | |
44 | PublicKey: pub, | |
45 | n: fromBig(pub.N), | |
46 | e: fromBig(big.NewInt(int64(pub.E))), | |
47 | } | |
48 | ||
49 | pk.setFingerPrintAndKeyId() | |
50 | return pk | |
51 | } | |
52 | ||
53 | func (pk *PublicKeyV3) parse(r io.Reader) (err error) { | |
54 | // RFC 4880, section 5.5.2 | |
55 | var buf [8]byte | |
56 | if _, err = readFull(r, buf[:]); err != nil { | |
57 | return | |
58 | } | |
59 | if buf[0] < 2 || buf[0] > 3 { | |
60 | return errors.UnsupportedError("public key version") | |
61 | } | |
62 | pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0) | |
63 | pk.DaysToExpire = binary.BigEndian.Uint16(buf[5:7]) | |
64 | pk.PubKeyAlgo = PublicKeyAlgorithm(buf[7]) | |
65 | switch pk.PubKeyAlgo { | |
66 | case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: | |
67 | err = pk.parseRSA(r) | |
68 | default: | |
69 | err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo))) | |
70 | } | |
71 | if err != nil { | |
72 | return | |
73 | } | |
74 | ||
75 | pk.setFingerPrintAndKeyId() | |
76 | return | |
77 | } | |
78 | ||
79 | func (pk *PublicKeyV3) setFingerPrintAndKeyId() { | |
80 | // RFC 4880, section 12.2 | |
81 | fingerPrint := md5.New() | |
82 | fingerPrint.Write(pk.n.bytes) | |
83 | fingerPrint.Write(pk.e.bytes) | |
84 | fingerPrint.Sum(pk.Fingerprint[:0]) | |
85 | pk.KeyId = binary.BigEndian.Uint64(pk.n.bytes[len(pk.n.bytes)-8:]) | |
86 | } | |
87 | ||
88 | // parseRSA parses RSA public key material from the given Reader. See RFC 4880, | |
89 | // section 5.5.2. | |
90 | func (pk *PublicKeyV3) parseRSA(r io.Reader) (err error) { | |
91 | if pk.n.bytes, pk.n.bitLength, err = readMPI(r); err != nil { | |
92 | return | |
93 | } | |
94 | if pk.e.bytes, pk.e.bitLength, err = readMPI(r); err != nil { | |
95 | return | |
96 | } | |
97 | ||
98 | // RFC 4880 Section 12.2 requires the low 8 bytes of the | |
99 | // modulus to form the key id. | |
100 | if len(pk.n.bytes) < 8 { | |
101 | return errors.StructuralError("v3 public key modulus is too short") | |
102 | } | |
103 | if len(pk.e.bytes) > 3 { | |
104 | err = errors.UnsupportedError("large public exponent") | |
105 | return | |
106 | } | |
107 | rsa := &rsa.PublicKey{N: new(big.Int).SetBytes(pk.n.bytes)} | |
108 | for i := 0; i < len(pk.e.bytes); i++ { | |
109 | rsa.E <<= 8 | |
110 | rsa.E |= int(pk.e.bytes[i]) | |
111 | } | |
112 | pk.PublicKey = rsa | |
113 | return | |
114 | } | |
115 | ||
116 | // SerializeSignaturePrefix writes the prefix for this public key to the given Writer. | |
117 | // The prefix is used when calculating a signature over this public key. See | |
118 | // RFC 4880, section 5.2.4. | |
119 | func (pk *PublicKeyV3) SerializeSignaturePrefix(w io.Writer) { | |
120 | var pLength uint16 | |
121 | switch pk.PubKeyAlgo { | |
122 | case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: | |
123 | pLength += 2 + uint16(len(pk.n.bytes)) | |
124 | pLength += 2 + uint16(len(pk.e.bytes)) | |
125 | default: | |
126 | panic("unknown public key algorithm") | |
127 | } | |
128 | pLength += 6 | |
129 | w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}) | |
130 | return | |
131 | } | |
132 | ||
133 | func (pk *PublicKeyV3) Serialize(w io.Writer) (err error) { | |
134 | length := 8 // 8 byte header | |
135 | ||
136 | switch pk.PubKeyAlgo { | |
137 | case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: | |
138 | length += 2 + len(pk.n.bytes) | |
139 | length += 2 + len(pk.e.bytes) | |
140 | default: | |
141 | panic("unknown public key algorithm") | |
142 | } | |
143 | ||
144 | packetType := packetTypePublicKey | |
145 | if pk.IsSubkey { | |
146 | packetType = packetTypePublicSubkey | |
147 | } | |
148 | if err = serializeHeader(w, packetType, length); err != nil { | |
149 | return | |
150 | } | |
151 | return pk.serializeWithoutHeaders(w) | |
152 | } | |
153 | ||
154 | // serializeWithoutHeaders marshals the PublicKey to w in the form of an | |
155 | // OpenPGP public key packet, not including the packet header. | |
156 | func (pk *PublicKeyV3) serializeWithoutHeaders(w io.Writer) (err error) { | |
157 | var buf [8]byte | |
158 | // Version 3 | |
159 | buf[0] = 3 | |
160 | // Creation time | |
161 | t := uint32(pk.CreationTime.Unix()) | |
162 | buf[1] = byte(t >> 24) | |
163 | buf[2] = byte(t >> 16) | |
164 | buf[3] = byte(t >> 8) | |
165 | buf[4] = byte(t) | |
166 | // Days to expire | |
167 | buf[5] = byte(pk.DaysToExpire >> 8) | |
168 | buf[6] = byte(pk.DaysToExpire) | |
169 | // Public key algorithm | |
170 | buf[7] = byte(pk.PubKeyAlgo) | |
171 | ||
172 | if _, err = w.Write(buf[:]); err != nil { | |
173 | return | |
174 | } | |
175 | ||
176 | switch pk.PubKeyAlgo { | |
177 | case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: | |
178 | return writeMPIs(w, pk.n, pk.e) | |
179 | } | |
180 | return errors.InvalidArgumentError("bad public-key algorithm") | |
181 | } | |
182 | ||
183 | // CanSign returns true iff this public key can generate signatures | |
184 | func (pk *PublicKeyV3) CanSign() bool { | |
185 | return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly | |
186 | } | |
187 | ||
188 | // VerifySignatureV3 returns nil iff sig is a valid signature, made by this | |
189 | // public key, of the data hashed into signed. signed is mutated by this call. | |
190 | func (pk *PublicKeyV3) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) { | |
191 | if !pk.CanSign() { | |
192 | return errors.InvalidArgumentError("public key cannot generate signatures") | |
193 | } | |
194 | ||
195 | suffix := make([]byte, 5) | |
196 | suffix[0] = byte(sig.SigType) | |
197 | binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix())) | |
198 | signed.Write(suffix) | |
199 | hashBytes := signed.Sum(nil) | |
200 | ||
201 | if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { | |
202 | return errors.SignatureError("hash tag doesn't match") | |
203 | } | |
204 | ||
205 | if pk.PubKeyAlgo != sig.PubKeyAlgo { | |
206 | return errors.InvalidArgumentError("public key and signature use different algorithms") | |
207 | } | |
208 | ||
209 | switch pk.PubKeyAlgo { | |
210 | case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: | |
211 | if err = rsa.VerifyPKCS1v15(pk.PublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil { | |
212 | return errors.SignatureError("RSA verification failure") | |
213 | } | |
214 | return | |
215 | default: | |
216 | // V3 public keys only support RSA. | |
217 | panic("shouldn't happen") | |
218 | } | |
219 | } | |
220 | ||
221 | // VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this | |
222 | // public key, that id is the identity of pub. | |
223 | func (pk *PublicKeyV3) VerifyUserIdSignatureV3(id string, pub *PublicKeyV3, sig *SignatureV3) (err error) { | |
224 | h, err := userIdSignatureV3Hash(id, pk, sig.Hash) | |
225 | if err != nil { | |
226 | return err | |
227 | } | |
228 | return pk.VerifySignatureV3(h, sig) | |
229 | } | |
230 | ||
231 | // VerifyKeySignatureV3 returns nil iff sig is a valid signature, made by this | |
232 | // public key, of signed. | |
233 | func (pk *PublicKeyV3) VerifyKeySignatureV3(signed *PublicKeyV3, sig *SignatureV3) (err error) { | |
234 | h, err := keySignatureHash(pk, signed, sig.Hash) | |
235 | if err != nil { | |
236 | return err | |
237 | } | |
238 | return pk.VerifySignatureV3(h, sig) | |
239 | } | |
240 | ||
241 | // userIdSignatureV3Hash returns a Hash of the message that needs to be signed | |
242 | // to assert that pk is a valid key for id. | |
243 | func userIdSignatureV3Hash(id string, pk signingKey, hfn crypto.Hash) (h hash.Hash, err error) { | |
244 | if !hfn.Available() { | |
245 | return nil, errors.UnsupportedError("hash function") | |
246 | } | |
247 | h = hfn.New() | |
248 | ||
249 | // RFC 4880, section 5.2.4 | |
250 | pk.SerializeSignaturePrefix(h) | |
251 | pk.serializeWithoutHeaders(h) | |
252 | ||
253 | h.Write([]byte(id)) | |
254 | ||
255 | return | |
256 | } | |
257 | ||
258 | // KeyIdString returns the public key's fingerprint in capital hex | |
259 | // (e.g. "6C7EE1B8621CC013"). | |
260 | func (pk *PublicKeyV3) KeyIdString() string { | |
261 | return fmt.Sprintf("%X", pk.KeyId) | |
262 | } | |
263 | ||
264 | // KeyIdShortString returns the short form of public key's fingerprint | |
265 | // in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). | |
266 | func (pk *PublicKeyV3) KeyIdShortString() string { | |
267 | return fmt.Sprintf("%X", pk.KeyId&0xFFFFFFFF) | |
268 | } | |
269 | ||
270 | // BitLength returns the bit length for the given public key. | |
271 | func (pk *PublicKeyV3) BitLength() (bitLength uint16, err error) { | |
272 | switch pk.PubKeyAlgo { | |
273 | case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: | |
274 | bitLength = pk.n.bitLength | |
275 | default: | |
276 | err = errors.InvalidArgumentError("bad public-key algorithm") | |
277 | } | |
278 | return | |
279 | } |