1
2
3
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
23
24
25
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
39
40
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
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
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
89
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
99
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
117
118
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
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
155
156 func (pk *PublicKeyV3) serializeWithoutHeaders(w io.Writer) (err error) {
157 var buf [8]byte
158
159 buf[0] = 3
160
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
167 buf[5] = byte(pk.DaysToExpire >> 8)
168 buf[6] = byte(pk.DaysToExpire)
169
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
184 func (pk *PublicKeyV3) CanSign() bool {
185 return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly
186 }
187
188
189
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
217 panic("shouldn't happen")
218 }
219 }
220
221
222
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
232
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
242
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
250 pk.SerializeSignaturePrefix(h)
251 pk.serializeWithoutHeaders(h)
252
253 h.Write([]byte(id))
254
255 return
256 }
257
258
259
260 func (pk *PublicKeyV3) KeyIdString() string {
261 return fmt.Sprintf("%X", pk.KeyId)
262 }
263
264
265
266 func (pk *PublicKeyV3) KeyIdShortString() string {
267 return fmt.Sprintf("%X", pk.KeyId&0xFFFFFFFF)
268 }
269
270
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 }
280
View as plain text