~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/golang.org/x/crypto/openpgp/packet/encrypted_key.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
        "crypto/rsa"
 
9
        "encoding/binary"
 
10
        "io"
 
11
        "math/big"
 
12
        "strconv"
 
13
 
 
14
        "golang.org/x/crypto/openpgp/elgamal"
 
15
        "golang.org/x/crypto/openpgp/errors"
 
16
)
 
17
 
 
18
const encryptedKeyVersion = 3
 
19
 
 
20
// EncryptedKey represents a public-key encrypted session key. See RFC 4880,
 
21
// section 5.1.
 
22
type EncryptedKey struct {
 
23
        KeyId      uint64
 
24
        Algo       PublicKeyAlgorithm
 
25
        CipherFunc CipherFunction // only valid after a successful Decrypt
 
26
        Key        []byte         // only valid after a successful Decrypt
 
27
 
 
28
        encryptedMPI1, encryptedMPI2 parsedMPI
 
29
}
 
30
 
 
31
func (e *EncryptedKey) parse(r io.Reader) (err error) {
 
32
        var buf [10]byte
 
33
        _, err = readFull(r, buf[:])
 
34
        if err != nil {
 
35
                return
 
36
        }
 
37
        if buf[0] != encryptedKeyVersion {
 
38
                return errors.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0])))
 
39
        }
 
40
        e.KeyId = binary.BigEndian.Uint64(buf[1:9])
 
41
        e.Algo = PublicKeyAlgorithm(buf[9])
 
42
        switch e.Algo {
 
43
        case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
 
44
                e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r)
 
45
        case PubKeyAlgoElGamal:
 
46
                e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r)
 
47
                if err != nil {
 
48
                        return
 
49
                }
 
50
                e.encryptedMPI2.bytes, e.encryptedMPI2.bitLength, err = readMPI(r)
 
51
        }
 
52
        _, err = consumeAll(r)
 
53
        return
 
54
}
 
55
 
 
56
func checksumKeyMaterial(key []byte) uint16 {
 
57
        var checksum uint16
 
58
        for _, v := range key {
 
59
                checksum += uint16(v)
 
60
        }
 
61
        return checksum
 
62
}
 
63
 
 
64
// Decrypt decrypts an encrypted session key with the given private key. The
 
65
// private key must have been decrypted first.
 
66
// If config is nil, sensible defaults will be used.
 
67
func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error {
 
68
        var err error
 
69
        var b []byte
 
70
 
 
71
        // TODO(agl): use session key decryption routines here to avoid
 
72
        // padding oracle attacks.
 
73
        switch priv.PubKeyAlgo {
 
74
        case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
 
75
                b, err = rsa.DecryptPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), e.encryptedMPI1.bytes)
 
76
        case PubKeyAlgoElGamal:
 
77
                c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes)
 
78
                c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes)
 
79
                b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2)
 
80
        default:
 
81
                err = errors.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo)))
 
82
        }
 
83
 
 
84
        if err != nil {
 
85
                return err
 
86
        }
 
87
 
 
88
        e.CipherFunc = CipherFunction(b[0])
 
89
        e.Key = b[1 : len(b)-2]
 
90
        expectedChecksum := uint16(b[len(b)-2])<<8 | uint16(b[len(b)-1])
 
91
        checksum := checksumKeyMaterial(e.Key)
 
92
        if checksum != expectedChecksum {
 
93
                return errors.StructuralError("EncryptedKey checksum incorrect")
 
94
        }
 
95
 
 
96
        return nil
 
97
}
 
98
 
 
99
// Serialize writes the encrypted key packet, e, to w.
 
100
func (e *EncryptedKey) Serialize(w io.Writer) error {
 
101
        var mpiLen int
 
102
        switch e.Algo {
 
103
        case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
 
104
                mpiLen = 2 + len(e.encryptedMPI1.bytes)
 
105
        case PubKeyAlgoElGamal:
 
106
                mpiLen = 2 + len(e.encryptedMPI1.bytes) + 2 + len(e.encryptedMPI2.bytes)
 
107
        default:
 
108
                return errors.InvalidArgumentError("don't know how to serialize encrypted key type " + strconv.Itoa(int(e.Algo)))
 
109
        }
 
110
 
 
111
        serializeHeader(w, packetTypeEncryptedKey, 1 /* version */ +8 /* key id */ +1 /* algo */ +mpiLen)
 
112
 
 
113
        w.Write([]byte{encryptedKeyVersion})
 
114
        binary.Write(w, binary.BigEndian, e.KeyId)
 
115
        w.Write([]byte{byte(e.Algo)})
 
116
 
 
117
        switch e.Algo {
 
118
        case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
 
119
                writeMPIs(w, e.encryptedMPI1)
 
120
        case PubKeyAlgoElGamal:
 
121
                writeMPIs(w, e.encryptedMPI1, e.encryptedMPI2)
 
122
        default:
 
123
                panic("internal error")
 
124
        }
 
125
 
 
126
        return nil
 
127
}
 
128
 
 
129
// SerializeEncryptedKey serializes an encrypted key packet to w that contains
 
130
// key, encrypted to pub.
 
131
// If config is nil, sensible defaults will be used.
 
132
func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, key []byte, config *Config) error {
 
133
        var buf [10]byte
 
134
        buf[0] = encryptedKeyVersion
 
135
        binary.BigEndian.PutUint64(buf[1:9], pub.KeyId)
 
136
        buf[9] = byte(pub.PubKeyAlgo)
 
137
 
 
138
        keyBlock := make([]byte, 1 /* cipher type */ +len(key)+2 /* checksum */)
 
139
        keyBlock[0] = byte(cipherFunc)
 
140
        copy(keyBlock[1:], key)
 
141
        checksum := checksumKeyMaterial(key)
 
142
        keyBlock[1+len(key)] = byte(checksum >> 8)
 
143
        keyBlock[1+len(key)+1] = byte(checksum)
 
144
 
 
145
        switch pub.PubKeyAlgo {
 
146
        case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
 
147
                return serializeEncryptedKeyRSA(w, config.Random(), buf, pub.PublicKey.(*rsa.PublicKey), keyBlock)
 
148
        case PubKeyAlgoElGamal:
 
149
                return serializeEncryptedKeyElGamal(w, config.Random(), buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock)
 
150
        case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly:
 
151
                return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
 
152
        }
 
153
 
 
154
        return errors.UnsupportedError("encrypting a key to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
 
155
}
 
156
 
 
157
func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub *rsa.PublicKey, keyBlock []byte) error {
 
158
        cipherText, err := rsa.EncryptPKCS1v15(rand, pub, keyBlock)
 
159
        if err != nil {
 
160
                return errors.InvalidArgumentError("RSA encryption failed: " + err.Error())
 
161
        }
 
162
 
 
163
        packetLen := 10 /* header length */ + 2 /* mpi size */ + len(cipherText)
 
164
 
 
165
        err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
 
166
        if err != nil {
 
167
                return err
 
168
        }
 
169
        _, err = w.Write(header[:])
 
170
        if err != nil {
 
171
                return err
 
172
        }
 
173
        return writeMPI(w, 8*uint16(len(cipherText)), cipherText)
 
174
}
 
175
 
 
176
func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte, pub *elgamal.PublicKey, keyBlock []byte) error {
 
177
        c1, c2, err := elgamal.Encrypt(rand, pub, keyBlock)
 
178
        if err != nil {
 
179
                return errors.InvalidArgumentError("ElGamal encryption failed: " + err.Error())
 
180
        }
 
181
 
 
182
        packetLen := 10 /* header length */
 
183
        packetLen += 2 /* mpi size */ + (c1.BitLen()+7)/8
 
184
        packetLen += 2 /* mpi size */ + (c2.BitLen()+7)/8
 
185
 
 
186
        err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
 
187
        if err != nil {
 
188
                return err
 
189
        }
 
190
        _, err = w.Write(header[:])
 
191
        if err != nil {
 
192
                return err
 
193
        }
 
194
        err = writeBig(w, c1)
 
195
        if err != nil {
 
196
                return err
 
197
        }
 
198
        return writeBig(w, c2)
 
199
}