~ubuntu-branches/ubuntu/vivid/golang/vivid

« back to all changes in this revision

Viewing changes to src/pkg/crypto/openpgp/packet/encrypted_key.go

  • Committer: Bazaar Package Importer
  • Author(s): Ondřej Surý
  • Date: 2011-08-03 17:04:59 UTC
  • mfrom: (14.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20110803170459-wzd99m3567y80ila
Tags: 1:59-1
* Imported Upstream version 59
* Refresh patches to a new release
* Fix FTBFS on ARM (Closes: #634270)
* Update version.bash to work with Debian packaging and not hg
  repository

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
package packet
6
6
 
7
7
import (
 
8
        "big"
 
9
        "crypto/openpgp/elgamal"
8
10
        "crypto/openpgp/error"
9
11
        "crypto/rand"
10
12
        "crypto/rsa"
14
16
        "strconv"
15
17
)
16
18
 
 
19
const encryptedKeyVersion = 3
 
20
 
17
21
// EncryptedKey represents a public-key encrypted session key. See RFC 4880,
18
22
// section 5.1.
19
23
type EncryptedKey struct {
20
24
        KeyId      uint64
21
25
        Algo       PublicKeyAlgorithm
22
 
        Encrypted  []byte
23
26
        CipherFunc CipherFunction // only valid after a successful Decrypt
24
27
        Key        []byte         // only valid after a successful Decrypt
 
28
 
 
29
        encryptedMPI1, encryptedMPI2 []byte
25
30
}
26
31
 
27
32
func (e *EncryptedKey) parse(r io.Reader) (err os.Error) {
30
35
        if err != nil {
31
36
                return
32
37
        }
33
 
        if buf[0] != 3 {
 
38
        if buf[0] != encryptedKeyVersion {
34
39
                return error.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0])))
35
40
        }
36
41
        e.KeyId = binary.BigEndian.Uint64(buf[1:9])
37
42
        e.Algo = PublicKeyAlgorithm(buf[9])
38
 
        if e.Algo == PubKeyAlgoRSA || e.Algo == PubKeyAlgoRSAEncryptOnly {
39
 
                e.Encrypted, _, err = readMPI(r)
 
43
        switch e.Algo {
 
44
        case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
 
45
                e.encryptedMPI1, _, err = readMPI(r)
 
46
        case PubKeyAlgoElGamal:
 
47
                e.encryptedMPI1, _, err = readMPI(r)
 
48
                if err != nil {
 
49
                        return
 
50
                }
 
51
                e.encryptedMPI2, _, err = readMPI(r)
40
52
        }
41
53
        _, err = consumeAll(r)
42
54
        return
43
55
}
44
56
 
45
 
// DecryptRSA decrypts an RSA encrypted session key with the given private key.
46
 
func (e *EncryptedKey) DecryptRSA(priv *rsa.PrivateKey) (err os.Error) {
47
 
        if e.Algo != PubKeyAlgoRSA && e.Algo != PubKeyAlgoRSAEncryptOnly {
48
 
                return error.InvalidArgumentError("EncryptedKey not RSA encrypted")
49
 
        }
50
 
        b, err := rsa.DecryptPKCS1v15(rand.Reader, priv, e.Encrypted)
 
57
func checksumKeyMaterial(key []byte) uint16 {
 
58
        var checksum uint16
 
59
        for _, v := range key {
 
60
                checksum += uint16(v)
 
61
        }
 
62
        return checksum
 
63
}
 
64
 
 
65
// Decrypt decrypts an encrypted session key with the given private key. The
 
66
// private key must have been decrypted first.
 
67
func (e *EncryptedKey) Decrypt(priv *PrivateKey) os.Error {
 
68
        var err os.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(rand.Reader, priv.PrivateKey.(*rsa.PrivateKey), e.encryptedMPI1)
 
76
        case PubKeyAlgoElGamal:
 
77
                c1 := new(big.Int).SetBytes(e.encryptedMPI1)
 
78
                c2 := new(big.Int).SetBytes(e.encryptedMPI2)
 
79
                b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2)
 
80
        default:
 
81
                err = error.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo)))
 
82
        }
 
83
 
51
84
        if err != nil {
52
 
                return
 
85
                return err
53
86
        }
 
87
 
54
88
        e.CipherFunc = CipherFunction(b[0])
55
89
        e.Key = b[1 : len(b)-2]
56
90
        expectedChecksum := uint16(b[len(b)-2])<<8 | uint16(b[len(b)-1])
57
 
        var checksum uint16
58
 
        for _, v := range e.Key {
59
 
                checksum += uint16(v)
60
 
        }
 
91
        checksum := checksumKeyMaterial(e.Key)
61
92
        if checksum != expectedChecksum {
62
93
                return error.StructuralError("EncryptedKey checksum incorrect")
63
94
        }
64
95
 
65
 
        return
 
96
        return nil
 
97
}
 
98
 
 
99
// SerializeEncryptedKey serializes an encrypted key packet to w that contains
 
100
// key, encrypted to pub.
 
101
func SerializeEncryptedKey(w io.Writer, rand io.Reader, pub *PublicKey, cipherFunc CipherFunction, key []byte) os.Error {
 
102
        var buf [10]byte
 
103
        buf[0] = encryptedKeyVersion
 
104
        binary.BigEndian.PutUint64(buf[1:9], pub.KeyId)
 
105
        buf[9] = byte(pub.PubKeyAlgo)
 
106
 
 
107
        keyBlock := make([]byte, 1 /* cipher type */ +len(key)+2 /* checksum */ )
 
108
        keyBlock[0] = byte(cipherFunc)
 
109
        copy(keyBlock[1:], key)
 
110
        checksum := checksumKeyMaterial(key)
 
111
        keyBlock[1+len(key)] = byte(checksum >> 8)
 
112
        keyBlock[1+len(key)+1] = byte(checksum)
 
113
 
 
114
        switch pub.PubKeyAlgo {
 
115
        case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
 
116
                return serializeEncryptedKeyRSA(w, rand, buf, pub.PublicKey.(*rsa.PublicKey), keyBlock)
 
117
        case PubKeyAlgoElGamal:
 
118
                return serializeEncryptedKeyElGamal(w, rand, buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock)
 
119
        case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly:
 
120
                return error.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
 
121
        }
 
122
 
 
123
        return error.UnsupportedError("encrypting a key to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
 
124
}
 
125
 
 
126
func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub *rsa.PublicKey, keyBlock []byte) os.Error {
 
127
        cipherText, err := rsa.EncryptPKCS1v15(rand, pub, keyBlock)
 
128
        if err != nil {
 
129
                return error.InvalidArgumentError("RSA encryption failed: " + err.String())
 
130
        }
 
131
 
 
132
        packetLen := 10 /* header length */ + 2 /* mpi size */ + len(cipherText)
 
133
 
 
134
        err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
 
135
        if err != nil {
 
136
                return err
 
137
        }
 
138
        _, err = w.Write(header[:])
 
139
        if err != nil {
 
140
                return err
 
141
        }
 
142
        return writeMPI(w, 8*uint16(len(cipherText)), cipherText)
 
143
}
 
144
 
 
145
func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte, pub *elgamal.PublicKey, keyBlock []byte) os.Error {
 
146
        c1, c2, err := elgamal.Encrypt(rand, pub, keyBlock)
 
147
        if err != nil {
 
148
                return error.InvalidArgumentError("ElGamal encryption failed: " + err.String())
 
149
        }
 
150
 
 
151
        packetLen := 10 /* header length */
 
152
        packetLen += 2 /* mpi size */ + (c1.BitLen()+7)/8
 
153
        packetLen += 2 /* mpi size */ + (c2.BitLen()+7)/8
 
154
 
 
155
        err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
 
156
        if err != nil {
 
157
                return err
 
158
        }
 
159
        _, err = w.Write(header[:])
 
160
        if err != nil {
 
161
                return err
 
162
        }
 
163
        err = writeBig(w, c1)
 
164
        if err != nil {
 
165
                return err
 
166
        }
 
167
        return writeBig(w, c2)
66
168
}