Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(776)

Side by Side Diff: openpgp/packet/private_key.go

Issue 5564059: code review 5564059: go.crypto: initial code (Closed)
Patch Set: diff -r b50a7fb49394 https://code.google.com/p/go.crypto Created 13 years, 2 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « openpgp/packet/packet_test.go ('k') | openpgp/packet/private_key_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
5 package packet
6
7 import (
8 "bytes"
9 "code.google.com/p/go.crypto/openpgp/elgamal"
10 "code.google.com/p/go.crypto/openpgp/errors"
11 "code.google.com/p/go.crypto/openpgp/s2k"
12 "crypto/cipher"
13 "crypto/dsa"
14 "crypto/rsa"
15 "crypto/sha1"
16 "io"
17 "io/ioutil"
18 "math/big"
19 "strconv"
20 "time"
21 )
22
23 // PrivateKey represents a possibly encrypted private key. See RFC 4880,
24 // section 5.5.3.
25 type PrivateKey struct {
26 PublicKey
27 Encrypted bool // if true then the private key is unavailable until Decrypt has been called.
28 encryptedData []byte
29 cipher CipherFunction
30 s2k func(out, in []byte)
31 PrivateKey interface{} // An *rsa.PrivateKey or *dsa.PrivateKey.
32 sha1Checksum bool
33 iv []byte
34 }
35
36 func NewRSAPrivateKey(currentTime time.Time, priv *rsa.PrivateKey) *PrivateKey {
37 pk := new(PrivateKey)
38 pk.PublicKey = *NewRSAPublicKey(currentTime, &priv.PublicKey)
39 pk.PrivateKey = priv
40 return pk
41 }
42
43 func NewDSAPrivateKey(currentTime time.Time, priv *dsa.PrivateKey) *PrivateKey {
44 pk := new(PrivateKey)
45 pk.PublicKey = *NewDSAPublicKey(currentTime, &priv.PublicKey)
46 pk.PrivateKey = priv
47 return pk
48 }
49
50 func (pk *PrivateKey) parse(r io.Reader) (err error) {
51 err = (&pk.PublicKey).parse(r)
52 if err != nil {
53 return
54 }
55 var buf [1]byte
56 _, err = readFull(r, buf[:])
57 if err != nil {
58 return
59 }
60
61 s2kType := buf[0]
62
63 switch s2kType {
64 case 0:
65 pk.s2k = nil
66 pk.Encrypted = false
67 case 254, 255:
68 _, err = readFull(r, buf[:])
69 if err != nil {
70 return
71 }
72 pk.cipher = CipherFunction(buf[0])
73 pk.Encrypted = true
74 pk.s2k, err = s2k.Parse(r)
75 if err != nil {
76 return
77 }
78 if s2kType == 254 {
79 pk.sha1Checksum = true
80 }
81 default:
82 return errors.UnsupportedError("deprecated s2k function in priva te key")
83 }
84
85 if pk.Encrypted {
86 blockSize := pk.cipher.blockSize()
87 if blockSize == 0 {
88 return errors.UnsupportedError("unsupported cipher in pr ivate key: " + strconv.Itoa(int(pk.cipher)))
89 }
90 pk.iv = make([]byte, blockSize)
91 _, err = readFull(r, pk.iv)
92 if err != nil {
93 return
94 }
95 }
96
97 pk.encryptedData, err = ioutil.ReadAll(r)
98 if err != nil {
99 return
100 }
101
102 if !pk.Encrypted {
103 return pk.parsePrivateKey(pk.encryptedData)
104 }
105
106 return
107 }
108
109 func mod64kHash(d []byte) uint16 {
110 var h uint16
111 for _, b := range d {
112 h += uint16(b)
113 }
114 return h
115 }
116
117 func (pk *PrivateKey) Serialize(w io.Writer) (err error) {
118 // TODO(agl): support encrypted private keys
119 buf := bytes.NewBuffer(nil)
120 err = pk.PublicKey.serializeWithoutHeaders(buf)
121 if err != nil {
122 return
123 }
124 buf.WriteByte(0 /* no encryption */ )
125
126 privateKeyBuf := bytes.NewBuffer(nil)
127
128 switch priv := pk.PrivateKey.(type) {
129 case *rsa.PrivateKey:
130 err = serializeRSAPrivateKey(privateKeyBuf, priv)
131 case *dsa.PrivateKey:
132 err = serializeDSAPrivateKey(privateKeyBuf, priv)
133 default:
134 err = errors.InvalidArgumentError("unknown private key type")
135 }
136 if err != nil {
137 return
138 }
139
140 ptype := packetTypePrivateKey
141 contents := buf.Bytes()
142 privateKeyBytes := privateKeyBuf.Bytes()
143 if pk.IsSubkey {
144 ptype = packetTypePrivateSubkey
145 }
146 err = serializeHeader(w, ptype, len(contents)+len(privateKeyBytes)+2)
147 if err != nil {
148 return
149 }
150 _, err = w.Write(contents)
151 if err != nil {
152 return
153 }
154 _, err = w.Write(privateKeyBytes)
155 if err != nil {
156 return
157 }
158
159 checksum := mod64kHash(privateKeyBytes)
160 var checksumBytes [2]byte
161 checksumBytes[0] = byte(checksum >> 8)
162 checksumBytes[1] = byte(checksum)
163 _, err = w.Write(checksumBytes[:])
164
165 return
166 }
167
168 func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error {
169 err := writeBig(w, priv.D)
170 if err != nil {
171 return err
172 }
173 err = writeBig(w, priv.Primes[1])
174 if err != nil {
175 return err
176 }
177 err = writeBig(w, priv.Primes[0])
178 if err != nil {
179 return err
180 }
181 return writeBig(w, priv.Precomputed.Qinv)
182 }
183
184 func serializeDSAPrivateKey(w io.Writer, priv *dsa.PrivateKey) error {
185 return writeBig(w, priv.X)
186 }
187
188 // Decrypt decrypts an encrypted private key using a passphrase.
189 func (pk *PrivateKey) Decrypt(passphrase []byte) error {
190 if !pk.Encrypted {
191 return nil
192 }
193
194 key := make([]byte, pk.cipher.KeySize())
195 pk.s2k(key, passphrase)
196 block := pk.cipher.new(key)
197 cfb := cipher.NewCFBDecrypter(block, pk.iv)
198
199 data := pk.encryptedData
200 cfb.XORKeyStream(data, data)
201
202 if pk.sha1Checksum {
203 if len(data) < sha1.Size {
204 return errors.StructuralError("truncated private key dat a")
205 }
206 h := sha1.New()
207 h.Write(data[:len(data)-sha1.Size])
208 sum := h.Sum(nil)
209 if !bytes.Equal(sum, data[len(data)-sha1.Size:]) {
210 return errors.StructuralError("private key checksum fail ure")
211 }
212 data = data[:len(data)-sha1.Size]
213 } else {
214 if len(data) < 2 {
215 return errors.StructuralError("truncated private key dat a")
216 }
217 var sum uint16
218 for i := 0; i < len(data)-2; i++ {
219 sum += uint16(data[i])
220 }
221 if data[len(data)-2] != uint8(sum>>8) ||
222 data[len(data)-1] != uint8(sum) {
223 return errors.StructuralError("private key checksum fail ure")
224 }
225 data = data[:len(data)-2]
226 }
227
228 return pk.parsePrivateKey(data)
229 }
230
231 func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) {
232 switch pk.PublicKey.PubKeyAlgo {
233 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoRSAEncryptOnly:
234 return pk.parseRSAPrivateKey(data)
235 case PubKeyAlgoDSA:
236 return pk.parseDSAPrivateKey(data)
237 case PubKeyAlgoElGamal:
238 return pk.parseElGamalPrivateKey(data)
239 }
240 panic("impossible")
241 }
242
243 func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) {
244 rsaPub := pk.PublicKey.PublicKey.(*rsa.PublicKey)
245 rsaPriv := new(rsa.PrivateKey)
246 rsaPriv.PublicKey = *rsaPub
247
248 buf := bytes.NewBuffer(data)
249 d, _, err := readMPI(buf)
250 if err != nil {
251 return
252 }
253 p, _, err := readMPI(buf)
254 if err != nil {
255 return
256 }
257 q, _, err := readMPI(buf)
258 if err != nil {
259 return
260 }
261
262 rsaPriv.D = new(big.Int).SetBytes(d)
263 rsaPriv.Primes = make([]*big.Int, 2)
264 rsaPriv.Primes[0] = new(big.Int).SetBytes(p)
265 rsaPriv.Primes[1] = new(big.Int).SetBytes(q)
266 rsaPriv.Precompute()
267 pk.PrivateKey = rsaPriv
268 pk.Encrypted = false
269 pk.encryptedData = nil
270
271 return nil
272 }
273
274 func (pk *PrivateKey) parseDSAPrivateKey(data []byte) (err error) {
275 dsaPub := pk.PublicKey.PublicKey.(*dsa.PublicKey)
276 dsaPriv := new(dsa.PrivateKey)
277 dsaPriv.PublicKey = *dsaPub
278
279 buf := bytes.NewBuffer(data)
280 x, _, err := readMPI(buf)
281 if err != nil {
282 return
283 }
284
285 dsaPriv.X = new(big.Int).SetBytes(x)
286 pk.PrivateKey = dsaPriv
287 pk.Encrypted = false
288 pk.encryptedData = nil
289
290 return nil
291 }
292
293 func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) {
294 pub := pk.PublicKey.PublicKey.(*elgamal.PublicKey)
295 priv := new(elgamal.PrivateKey)
296 priv.PublicKey = *pub
297
298 buf := bytes.NewBuffer(data)
299 x, _, err := readMPI(buf)
300 if err != nil {
301 return
302 }
303
304 priv.X = new(big.Int).SetBytes(x)
305 pk.PrivateKey = priv
306 pk.Encrypted = false
307 pk.encryptedData = nil
308
309 return nil
310 }
OLDNEW
« no previous file with comments | « openpgp/packet/packet_test.go ('k') | openpgp/packet/private_key_test.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b