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.
12 "crypto/openpgp/elgamal"
13 error_ "crypto/openpgp/error"
22 // PrivateKey represents a possibly encrypted private key. See RFC 4880,
24 type PrivateKey struct {
26 Encrypted bool // if true then the private key is unavailable until Decrypt has been called.
29 s2k func(out, in []byte)
30 PrivateKey interface{} // An *rsa.PrivateKey.
35 func NewRSAPrivateKey(currentTimeSecs uint32, priv *rsa.PrivateKey, isSubkey bool) *PrivateKey {
37 pk.PublicKey = *NewRSAPublicKey(currentTimeSecs, &priv.PublicKey, isSubkey)
42 func (pk *PrivateKey) parse(r io.Reader) (err error) {
43 err = (&pk.PublicKey).parse(r)
48 _, err = readFull(r, buf[:])
60 _, err = readFull(r, buf[:])
64 pk.cipher = CipherFunction(buf[0])
66 pk.s2k, err = s2k.Parse(r)
71 pk.sha1Checksum = true
74 return error_.UnsupportedError("deprecated s2k function in private key")
78 blockSize := pk.cipher.blockSize()
80 return error_.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher)))
82 pk.iv = make([]byte, blockSize)
83 _, err = readFull(r, pk.iv)
89 pk.encryptedData, err = ioutil.ReadAll(r)
95 return pk.parsePrivateKey(pk.encryptedData)
101 func mod64kHash(d []byte) uint16 {
103 for i := 0; i < len(d); i += 2 {
104 v := uint16(d[i]) << 8
113 func (pk *PrivateKey) Serialize(w io.Writer) (err error) {
114 // TODO(agl): support encrypted private keys
115 buf := bytes.NewBuffer(nil)
116 err = pk.PublicKey.serializeWithoutHeaders(buf)
120 buf.WriteByte(0 /* no encryption */ )
122 privateKeyBuf := bytes.NewBuffer(nil)
124 switch priv := pk.PrivateKey.(type) {
125 case *rsa.PrivateKey:
126 err = serializeRSAPrivateKey(privateKeyBuf, priv)
128 err = error_.InvalidArgumentError("non-RSA private key")
134 ptype := packetTypePrivateKey
135 contents := buf.Bytes()
136 privateKeyBytes := privateKeyBuf.Bytes()
138 ptype = packetTypePrivateSubkey
140 err = serializeHeader(w, ptype, len(contents)+len(privateKeyBytes)+2)
144 _, err = w.Write(contents)
148 _, err = w.Write(privateKeyBytes)
153 checksum := mod64kHash(privateKeyBytes)
154 var checksumBytes [2]byte
155 checksumBytes[0] = byte(checksum >> 8)
156 checksumBytes[1] = byte(checksum)
157 _, err = w.Write(checksumBytes[:])
162 func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error {
163 err := writeBig(w, priv.D)
167 err = writeBig(w, priv.Primes[1])
171 err = writeBig(w, priv.Primes[0])
175 return writeBig(w, priv.Precomputed.Qinv)
178 // Decrypt decrypts an encrypted private key using a passphrase.
179 func (pk *PrivateKey) Decrypt(passphrase []byte) error {
184 key := make([]byte, pk.cipher.KeySize())
185 pk.s2k(key, passphrase)
186 block := pk.cipher.new(key)
187 cfb := cipher.NewCFBDecrypter(block, pk.iv)
189 data := pk.encryptedData
190 cfb.XORKeyStream(data, data)
193 if len(data) < sha1.Size {
194 return error_.StructuralError("truncated private key data")
197 h.Write(data[:len(data)-sha1.Size])
199 if !bytes.Equal(sum, data[len(data)-sha1.Size:]) {
200 return error_.StructuralError("private key checksum failure")
202 data = data[:len(data)-sha1.Size]
205 return error_.StructuralError("truncated private key data")
208 for i := 0; i < len(data)-2; i++ {
209 sum += uint16(data[i])
211 if data[len(data)-2] != uint8(sum>>8) ||
212 data[len(data)-1] != uint8(sum) {
213 return error_.StructuralError("private key checksum failure")
215 data = data[:len(data)-2]
218 return pk.parsePrivateKey(data)
221 func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) {
222 switch pk.PublicKey.PubKeyAlgo {
223 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoRSAEncryptOnly:
224 return pk.parseRSAPrivateKey(data)
226 return pk.parseDSAPrivateKey(data)
227 case PubKeyAlgoElGamal:
228 return pk.parseElGamalPrivateKey(data)
233 func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) {
234 rsaPub := pk.PublicKey.PublicKey.(*rsa.PublicKey)
235 rsaPriv := new(rsa.PrivateKey)
236 rsaPriv.PublicKey = *rsaPub
238 buf := bytes.NewBuffer(data)
239 d, _, err := readMPI(buf)
243 p, _, err := readMPI(buf)
247 q, _, err := readMPI(buf)
252 rsaPriv.D = new(big.Int).SetBytes(d)
253 rsaPriv.Primes = make([]*big.Int, 2)
254 rsaPriv.Primes[0] = new(big.Int).SetBytes(p)
255 rsaPriv.Primes[1] = new(big.Int).SetBytes(q)
257 pk.PrivateKey = rsaPriv
259 pk.encryptedData = nil
264 func (pk *PrivateKey) parseDSAPrivateKey(data []byte) (err error) {
265 dsaPub := pk.PublicKey.PublicKey.(*dsa.PublicKey)
266 dsaPriv := new(dsa.PrivateKey)
267 dsaPriv.PublicKey = *dsaPub
269 buf := bytes.NewBuffer(data)
270 x, _, err := readMPI(buf)
275 dsaPriv.X = new(big.Int).SetBytes(x)
276 pk.PrivateKey = dsaPriv
278 pk.encryptedData = nil
283 func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) {
284 pub := pk.PublicKey.PublicKey.(*elgamal.PublicKey)
285 priv := new(elgamal.PrivateKey)
286 priv.PublicKey = *pub
288 buf := bytes.NewBuffer(data)
289 x, _, err := readMPI(buf)
294 priv.X = new(big.Int).SetBytes(x)
297 pk.encryptedData = nil