1// Copyright 2013 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 "crypto" 9 "crypto/md5" 10 "crypto/rsa" 11 "encoding/binary" 12 "fmt" 13 "hash" 14 "io" 15 "math/big" 16 "strconv" 17 "time" 18 19 "golang.org/x/crypto/openpgp/errors" 20) 21 22// PublicKeyV3 represents older, version 3 public keys. These keys are less secure and 23// should not be used for signing or encrypting. They are supported here only for 24// parsing version 3 key material and validating signatures. 25// See RFC 4880, section 5.5.2. 26type PublicKeyV3 struct { 27 CreationTime time.Time 28 DaysToExpire uint16 29 PubKeyAlgo PublicKeyAlgorithm 30 PublicKey *rsa.PublicKey 31 Fingerprint [16]byte 32 KeyId uint64 33 IsSubkey bool 34 35 n, e parsedMPI 36} 37 38// newRSAPublicKeyV3 returns a PublicKey that wraps the given rsa.PublicKey. 39// Included here for testing purposes only. RFC 4880, section 5.5.2: 40// "an implementation MUST NOT generate a V3 key, but MAY accept it." 41func newRSAPublicKeyV3(creationTime time.Time, pub *rsa.PublicKey) *PublicKeyV3 { 42 pk := &PublicKeyV3{ 43 CreationTime: creationTime, 44 PublicKey: pub, 45 n: fromBig(pub.N), 46 e: fromBig(big.NewInt(int64(pub.E))), 47 } 48 49 pk.setFingerPrintAndKeyId() 50 return pk 51} 52 53func (pk *PublicKeyV3) parse(r io.Reader) (err error) { 54 // RFC 4880, section 5.5.2 55 var buf [8]byte 56 if _, err = readFull(r, buf[:]); err != nil { 57 return 58 } 59 if buf[0] < 2 || buf[0] > 3 { 60 return errors.UnsupportedError("public key version") 61 } 62 pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0) 63 pk.DaysToExpire = binary.BigEndian.Uint16(buf[5:7]) 64 pk.PubKeyAlgo = PublicKeyAlgorithm(buf[7]) 65 switch pk.PubKeyAlgo { 66 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: 67 err = pk.parseRSA(r) 68 default: 69 err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo))) 70 } 71 if err != nil { 72 return 73 } 74 75 pk.setFingerPrintAndKeyId() 76 return 77} 78 79func (pk *PublicKeyV3) setFingerPrintAndKeyId() { 80 // RFC 4880, section 12.2 81 fingerPrint := md5.New() 82 fingerPrint.Write(pk.n.bytes) 83 fingerPrint.Write(pk.e.bytes) 84 fingerPrint.Sum(pk.Fingerprint[:0]) 85 pk.KeyId = binary.BigEndian.Uint64(pk.n.bytes[len(pk.n.bytes)-8:]) 86} 87 88// parseRSA parses RSA public key material from the given Reader. See RFC 4880, 89// section 5.5.2. 90func (pk *PublicKeyV3) parseRSA(r io.Reader) (err error) { 91 if pk.n.bytes, pk.n.bitLength, err = readMPI(r); err != nil { 92 return 93 } 94 if pk.e.bytes, pk.e.bitLength, err = readMPI(r); err != nil { 95 return 96 } 97 98 // RFC 4880 Section 12.2 requires the low 8 bytes of the 99 // modulus to form the key id. 100 if len(pk.n.bytes) < 8 { 101 return errors.StructuralError("v3 public key modulus is too short") 102 } 103 if len(pk.e.bytes) > 3 { 104 err = errors.UnsupportedError("large public exponent") 105 return 106 } 107 rsa := &rsa.PublicKey{N: new(big.Int).SetBytes(pk.n.bytes)} 108 for i := 0; i < len(pk.e.bytes); i++ { 109 rsa.E <<= 8 110 rsa.E |= int(pk.e.bytes[i]) 111 } 112 pk.PublicKey = rsa 113 return 114} 115 116// SerializeSignaturePrefix writes the prefix for this public key to the given Writer. 117// The prefix is used when calculating a signature over this public key. See 118// RFC 4880, section 5.2.4. 119func (pk *PublicKeyV3) SerializeSignaturePrefix(w io.Writer) { 120 var pLength uint16 121 switch pk.PubKeyAlgo { 122 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: 123 pLength += 2 + uint16(len(pk.n.bytes)) 124 pLength += 2 + uint16(len(pk.e.bytes)) 125 default: 126 panic("unknown public key algorithm") 127 } 128 pLength += 6 129 w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}) 130 return 131} 132 133func (pk *PublicKeyV3) Serialize(w io.Writer) (err error) { 134 length := 8 // 8 byte header 135 136 switch pk.PubKeyAlgo { 137 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: 138 length += 2 + len(pk.n.bytes) 139 length += 2 + len(pk.e.bytes) 140 default: 141 panic("unknown public key algorithm") 142 } 143 144 packetType := packetTypePublicKey 145 if pk.IsSubkey { 146 packetType = packetTypePublicSubkey 147 } 148 if err = serializeHeader(w, packetType, length); err != nil { 149 return 150 } 151 return pk.serializeWithoutHeaders(w) 152} 153 154// serializeWithoutHeaders marshals the PublicKey to w in the form of an 155// OpenPGP public key packet, not including the packet header. 156func (pk *PublicKeyV3) serializeWithoutHeaders(w io.Writer) (err error) { 157 var buf [8]byte 158 // Version 3 159 buf[0] = 3 160 // Creation time 161 t := uint32(pk.CreationTime.Unix()) 162 buf[1] = byte(t >> 24) 163 buf[2] = byte(t >> 16) 164 buf[3] = byte(t >> 8) 165 buf[4] = byte(t) 166 // Days to expire 167 buf[5] = byte(pk.DaysToExpire >> 8) 168 buf[6] = byte(pk.DaysToExpire) 169 // Public key algorithm 170 buf[7] = byte(pk.PubKeyAlgo) 171 172 if _, err = w.Write(buf[:]); err != nil { 173 return 174 } 175 176 switch pk.PubKeyAlgo { 177 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: 178 return writeMPIs(w, pk.n, pk.e) 179 } 180 return errors.InvalidArgumentError("bad public-key algorithm") 181} 182 183// CanSign returns true iff this public key can generate signatures 184func (pk *PublicKeyV3) CanSign() bool { 185 return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly 186} 187 188// VerifySignatureV3 returns nil iff sig is a valid signature, made by this 189// public key, of the data hashed into signed. signed is mutated by this call. 190func (pk *PublicKeyV3) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) { 191 if !pk.CanSign() { 192 return errors.InvalidArgumentError("public key cannot generate signatures") 193 } 194 195 suffix := make([]byte, 5) 196 suffix[0] = byte(sig.SigType) 197 binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix())) 198 signed.Write(suffix) 199 hashBytes := signed.Sum(nil) 200 201 if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { 202 return errors.SignatureError("hash tag doesn't match") 203 } 204 205 if pk.PubKeyAlgo != sig.PubKeyAlgo { 206 return errors.InvalidArgumentError("public key and signature use different algorithms") 207 } 208 209 switch pk.PubKeyAlgo { 210 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: 211 if err = rsa.VerifyPKCS1v15(pk.PublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil { 212 return errors.SignatureError("RSA verification failure") 213 } 214 return 215 default: 216 // V3 public keys only support RSA. 217 panic("shouldn't happen") 218 } 219} 220 221// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this 222// public key, that id is the identity of pub. 223func (pk *PublicKeyV3) VerifyUserIdSignatureV3(id string, pub *PublicKeyV3, sig *SignatureV3) (err error) { 224 h, err := userIdSignatureV3Hash(id, pk, sig.Hash) 225 if err != nil { 226 return err 227 } 228 return pk.VerifySignatureV3(h, sig) 229} 230 231// VerifyKeySignatureV3 returns nil iff sig is a valid signature, made by this 232// public key, of signed. 233func (pk *PublicKeyV3) VerifyKeySignatureV3(signed *PublicKeyV3, sig *SignatureV3) (err error) { 234 h, err := keySignatureHash(pk, signed, sig.Hash) 235 if err != nil { 236 return err 237 } 238 return pk.VerifySignatureV3(h, sig) 239} 240 241// userIdSignatureV3Hash returns a Hash of the message that needs to be signed 242// to assert that pk is a valid key for id. 243func userIdSignatureV3Hash(id string, pk signingKey, hfn crypto.Hash) (h hash.Hash, err error) { 244 if !hfn.Available() { 245 return nil, errors.UnsupportedError("hash function") 246 } 247 h = hfn.New() 248 249 // RFC 4880, section 5.2.4 250 pk.SerializeSignaturePrefix(h) 251 pk.serializeWithoutHeaders(h) 252 253 h.Write([]byte(id)) 254 255 return 256} 257 258// KeyIdString returns the public key's fingerprint in capital hex 259// (e.g. "6C7EE1B8621CC013"). 260func (pk *PublicKeyV3) KeyIdString() string { 261 return fmt.Sprintf("%X", pk.KeyId) 262} 263 264// KeyIdShortString returns the short form of public key's fingerprint 265// in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). 266func (pk *PublicKeyV3) KeyIdShortString() string { 267 return fmt.Sprintf("%X", pk.KeyId&0xFFFFFFFF) 268} 269 270// BitLength returns the bit length for the given public key. 271func (pk *PublicKeyV3) BitLength() (bitLength uint16, err error) { 272 switch pk.PubKeyAlgo { 273 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: 274 bitLength = pk.n.bitLength 275 default: 276 err = errors.InvalidArgumentError("bad public-key algorithm") 277 } 278 return 279} 280