]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blame - vendor/golang.org/x/crypto/openpgp/packet/private_key.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / golang.org / x / crypto / openpgp / packet / private_key.go
CommitLineData
c680a8e1
RS
1// Copyright 2011 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
5package packet
6
7import (
8 "bytes"
9 "crypto"
10 "crypto/cipher"
11 "crypto/dsa"
12 "crypto/ecdsa"
13 "crypto/rsa"
14 "crypto/sha1"
15 "io"
16 "io/ioutil"
17 "math/big"
18 "strconv"
19 "time"
20
21 "golang.org/x/crypto/openpgp/elgamal"
22 "golang.org/x/crypto/openpgp/errors"
23 "golang.org/x/crypto/openpgp/s2k"
24)
25
26// PrivateKey represents a possibly encrypted private key. See RFC 4880,
27// section 5.5.3.
28type PrivateKey struct {
29 PublicKey
30 Encrypted bool // if true then the private key is unavailable until Decrypt has been called.
31 encryptedData []byte
32 cipher CipherFunction
33 s2k func(out, in []byte)
34 PrivateKey interface{} // An *{rsa|dsa|ecdsa}.PrivateKey or a crypto.Signer.
35 sha1Checksum bool
36 iv []byte
37}
38
39func NewRSAPrivateKey(currentTime time.Time, priv *rsa.PrivateKey) *PrivateKey {
40 pk := new(PrivateKey)
41 pk.PublicKey = *NewRSAPublicKey(currentTime, &priv.PublicKey)
42 pk.PrivateKey = priv
43 return pk
44}
45
46func NewDSAPrivateKey(currentTime time.Time, priv *dsa.PrivateKey) *PrivateKey {
47 pk := new(PrivateKey)
48 pk.PublicKey = *NewDSAPublicKey(currentTime, &priv.PublicKey)
49 pk.PrivateKey = priv
50 return pk
51}
52
53func NewElGamalPrivateKey(currentTime time.Time, priv *elgamal.PrivateKey) *PrivateKey {
54 pk := new(PrivateKey)
55 pk.PublicKey = *NewElGamalPublicKey(currentTime, &priv.PublicKey)
56 pk.PrivateKey = priv
57 return pk
58}
59
60func NewECDSAPrivateKey(currentTime time.Time, priv *ecdsa.PrivateKey) *PrivateKey {
61 pk := new(PrivateKey)
62 pk.PublicKey = *NewECDSAPublicKey(currentTime, &priv.PublicKey)
63 pk.PrivateKey = priv
64 return pk
65}
66
107c1cdb 67// NewSignerPrivateKey creates a PrivateKey from a crypto.Signer that
c680a8e1
RS
68// implements RSA or ECDSA.
69func NewSignerPrivateKey(currentTime time.Time, signer crypto.Signer) *PrivateKey {
70 pk := new(PrivateKey)
107c1cdb
ND
71 // In general, the public Keys should be used as pointers. We still
72 // type-switch on the values, for backwards-compatibility.
c680a8e1 73 switch pubkey := signer.Public().(type) {
107c1cdb
ND
74 case *rsa.PublicKey:
75 pk.PublicKey = *NewRSAPublicKey(currentTime, pubkey)
c680a8e1
RS
76 case rsa.PublicKey:
77 pk.PublicKey = *NewRSAPublicKey(currentTime, &pubkey)
107c1cdb
ND
78 case *ecdsa.PublicKey:
79 pk.PublicKey = *NewECDSAPublicKey(currentTime, pubkey)
c680a8e1
RS
80 case ecdsa.PublicKey:
81 pk.PublicKey = *NewECDSAPublicKey(currentTime, &pubkey)
82 default:
83 panic("openpgp: unknown crypto.Signer type in NewSignerPrivateKey")
84 }
85 pk.PrivateKey = signer
86 return pk
87}
88
89func (pk *PrivateKey) parse(r io.Reader) (err error) {
90 err = (&pk.PublicKey).parse(r)
91 if err != nil {
92 return
93 }
94 var buf [1]byte
95 _, err = readFull(r, buf[:])
96 if err != nil {
97 return
98 }
99
100 s2kType := buf[0]
101
102 switch s2kType {
103 case 0:
104 pk.s2k = nil
105 pk.Encrypted = false
106 case 254, 255:
107 _, err = readFull(r, buf[:])
108 if err != nil {
109 return
110 }
111 pk.cipher = CipherFunction(buf[0])
112 pk.Encrypted = true
113 pk.s2k, err = s2k.Parse(r)
114 if err != nil {
115 return
116 }
117 if s2kType == 254 {
118 pk.sha1Checksum = true
119 }
120 default:
121 return errors.UnsupportedError("deprecated s2k function in private key")
122 }
123
124 if pk.Encrypted {
125 blockSize := pk.cipher.blockSize()
126 if blockSize == 0 {
127 return errors.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher)))
128 }
129 pk.iv = make([]byte, blockSize)
130 _, err = readFull(r, pk.iv)
131 if err != nil {
132 return
133 }
134 }
135
136 pk.encryptedData, err = ioutil.ReadAll(r)
137 if err != nil {
138 return
139 }
140
141 if !pk.Encrypted {
142 return pk.parsePrivateKey(pk.encryptedData)
143 }
144
145 return
146}
147
148func mod64kHash(d []byte) uint16 {
149 var h uint16
150 for _, b := range d {
151 h += uint16(b)
152 }
153 return h
154}
155
156func (pk *PrivateKey) Serialize(w io.Writer) (err error) {
157 // TODO(agl): support encrypted private keys
158 buf := bytes.NewBuffer(nil)
159 err = pk.PublicKey.serializeWithoutHeaders(buf)
160 if err != nil {
161 return
162 }
163 buf.WriteByte(0 /* no encryption */)
164
165 privateKeyBuf := bytes.NewBuffer(nil)
166
167 switch priv := pk.PrivateKey.(type) {
168 case *rsa.PrivateKey:
169 err = serializeRSAPrivateKey(privateKeyBuf, priv)
170 case *dsa.PrivateKey:
171 err = serializeDSAPrivateKey(privateKeyBuf, priv)
172 case *elgamal.PrivateKey:
173 err = serializeElGamalPrivateKey(privateKeyBuf, priv)
174 case *ecdsa.PrivateKey:
175 err = serializeECDSAPrivateKey(privateKeyBuf, priv)
176 default:
177 err = errors.InvalidArgumentError("unknown private key type")
178 }
179 if err != nil {
180 return
181 }
182
183 ptype := packetTypePrivateKey
184 contents := buf.Bytes()
185 privateKeyBytes := privateKeyBuf.Bytes()
186 if pk.IsSubkey {
187 ptype = packetTypePrivateSubkey
188 }
189 err = serializeHeader(w, ptype, len(contents)+len(privateKeyBytes)+2)
190 if err != nil {
191 return
192 }
193 _, err = w.Write(contents)
194 if err != nil {
195 return
196 }
197 _, err = w.Write(privateKeyBytes)
198 if err != nil {
199 return
200 }
201
202 checksum := mod64kHash(privateKeyBytes)
203 var checksumBytes [2]byte
204 checksumBytes[0] = byte(checksum >> 8)
205 checksumBytes[1] = byte(checksum)
206 _, err = w.Write(checksumBytes[:])
207
208 return
209}
210
211func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error {
212 err := writeBig(w, priv.D)
213 if err != nil {
214 return err
215 }
216 err = writeBig(w, priv.Primes[1])
217 if err != nil {
218 return err
219 }
220 err = writeBig(w, priv.Primes[0])
221 if err != nil {
222 return err
223 }
224 return writeBig(w, priv.Precomputed.Qinv)
225}
226
227func serializeDSAPrivateKey(w io.Writer, priv *dsa.PrivateKey) error {
228 return writeBig(w, priv.X)
229}
230
231func serializeElGamalPrivateKey(w io.Writer, priv *elgamal.PrivateKey) error {
232 return writeBig(w, priv.X)
233}
234
235func serializeECDSAPrivateKey(w io.Writer, priv *ecdsa.PrivateKey) error {
236 return writeBig(w, priv.D)
237}
238
239// Decrypt decrypts an encrypted private key using a passphrase.
240func (pk *PrivateKey) Decrypt(passphrase []byte) error {
241 if !pk.Encrypted {
242 return nil
243 }
244
245 key := make([]byte, pk.cipher.KeySize())
246 pk.s2k(key, passphrase)
247 block := pk.cipher.new(key)
248 cfb := cipher.NewCFBDecrypter(block, pk.iv)
249
250 data := make([]byte, len(pk.encryptedData))
251 cfb.XORKeyStream(data, pk.encryptedData)
252
253 if pk.sha1Checksum {
254 if len(data) < sha1.Size {
255 return errors.StructuralError("truncated private key data")
256 }
257 h := sha1.New()
258 h.Write(data[:len(data)-sha1.Size])
259 sum := h.Sum(nil)
260 if !bytes.Equal(sum, data[len(data)-sha1.Size:]) {
261 return errors.StructuralError("private key checksum failure")
262 }
263 data = data[:len(data)-sha1.Size]
264 } else {
265 if len(data) < 2 {
266 return errors.StructuralError("truncated private key data")
267 }
268 var sum uint16
269 for i := 0; i < len(data)-2; i++ {
270 sum += uint16(data[i])
271 }
272 if data[len(data)-2] != uint8(sum>>8) ||
273 data[len(data)-1] != uint8(sum) {
274 return errors.StructuralError("private key checksum failure")
275 }
276 data = data[:len(data)-2]
277 }
278
279 return pk.parsePrivateKey(data)
280}
281
282func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) {
283 switch pk.PublicKey.PubKeyAlgo {
284 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoRSAEncryptOnly:
285 return pk.parseRSAPrivateKey(data)
286 case PubKeyAlgoDSA:
287 return pk.parseDSAPrivateKey(data)
288 case PubKeyAlgoElGamal:
289 return pk.parseElGamalPrivateKey(data)
290 case PubKeyAlgoECDSA:
291 return pk.parseECDSAPrivateKey(data)
292 }
293 panic("impossible")
294}
295
296func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) {
297 rsaPub := pk.PublicKey.PublicKey.(*rsa.PublicKey)
298 rsaPriv := new(rsa.PrivateKey)
299 rsaPriv.PublicKey = *rsaPub
300
301 buf := bytes.NewBuffer(data)
302 d, _, err := readMPI(buf)
303 if err != nil {
304 return
305 }
306 p, _, err := readMPI(buf)
307 if err != nil {
308 return
309 }
310 q, _, err := readMPI(buf)
311 if err != nil {
312 return
313 }
314
315 rsaPriv.D = new(big.Int).SetBytes(d)
316 rsaPriv.Primes = make([]*big.Int, 2)
317 rsaPriv.Primes[0] = new(big.Int).SetBytes(p)
318 rsaPriv.Primes[1] = new(big.Int).SetBytes(q)
319 if err := rsaPriv.Validate(); err != nil {
320 return err
321 }
322 rsaPriv.Precompute()
323 pk.PrivateKey = rsaPriv
324 pk.Encrypted = false
325 pk.encryptedData = nil
326
327 return nil
328}
329
330func (pk *PrivateKey) parseDSAPrivateKey(data []byte) (err error) {
331 dsaPub := pk.PublicKey.PublicKey.(*dsa.PublicKey)
332 dsaPriv := new(dsa.PrivateKey)
333 dsaPriv.PublicKey = *dsaPub
334
335 buf := bytes.NewBuffer(data)
336 x, _, err := readMPI(buf)
337 if err != nil {
338 return
339 }
340
341 dsaPriv.X = new(big.Int).SetBytes(x)
342 pk.PrivateKey = dsaPriv
343 pk.Encrypted = false
344 pk.encryptedData = nil
345
346 return nil
347}
348
349func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) {
350 pub := pk.PublicKey.PublicKey.(*elgamal.PublicKey)
351 priv := new(elgamal.PrivateKey)
352 priv.PublicKey = *pub
353
354 buf := bytes.NewBuffer(data)
355 x, _, err := readMPI(buf)
356 if err != nil {
357 return
358 }
359
360 priv.X = new(big.Int).SetBytes(x)
361 pk.PrivateKey = priv
362 pk.Encrypted = false
363 pk.encryptedData = nil
364
365 return nil
366}
367
368func (pk *PrivateKey) parseECDSAPrivateKey(data []byte) (err error) {
369 ecdsaPub := pk.PublicKey.PublicKey.(*ecdsa.PublicKey)
370
371 buf := bytes.NewBuffer(data)
372 d, _, err := readMPI(buf)
373 if err != nil {
374 return
375 }
376
377 pk.PrivateKey = &ecdsa.PrivateKey{
378 PublicKey: *ecdsaPub,
379 D: new(big.Int).SetBytes(d),
380 }
381 pk.Encrypted = false
382 pk.encryptedData = nil
383
384 return nil
385}