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 5package packet 6 7import ( 8 "bytes" 9 "crypto" 10 "crypto/dsa" 11 "crypto/ecdsa" 12 "crypto/elliptic" 13 "crypto/rsa" 14 "crypto/sha1" 15 _ "crypto/sha256" 16 _ "crypto/sha512" 17 "encoding/binary" 18 "fmt" 19 "hash" 20 "io" 21 "math/big" 22 "strconv" 23 "time" 24 25 "golang.org/x/crypto/openpgp/elgamal" 26 "golang.org/x/crypto/openpgp/errors" 27) 28 29var ( 30 // NIST curve P-256 31 oidCurveP256 []byte = []byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07} 32 // NIST curve P-384 33 oidCurveP384 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x22} 34 // NIST curve P-521 35 oidCurveP521 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x23} 36) 37 38const maxOIDLength = 8 39 40// ecdsaKey stores the algorithm-specific fields for ECDSA keys. 41// as defined in RFC 6637, Section 9. 42type ecdsaKey struct { 43 // oid contains the OID byte sequence identifying the elliptic curve used 44 oid []byte 45 // p contains the elliptic curve point that represents the public key 46 p parsedMPI 47} 48 49// parseOID reads the OID for the curve as defined in RFC 6637, Section 9. 50func parseOID(r io.Reader) (oid []byte, err error) { 51 buf := make([]byte, maxOIDLength) 52 if _, err = readFull(r, buf[:1]); err != nil { 53 return 54 } 55 oidLen := buf[0] 56 if int(oidLen) > len(buf) { 57 err = errors.UnsupportedError("invalid oid length: " + strconv.Itoa(int(oidLen))) 58 return 59 } 60 oid = buf[:oidLen] 61 _, err = readFull(r, oid) 62 return 63} 64 65func (f *ecdsaKey) parse(r io.Reader) (err error) { 66 if f.oid, err = parseOID(r); err != nil { 67 return err 68 } 69 f.p.bytes, f.p.bitLength, err = readMPI(r) 70 return 71} 72 73func (f *ecdsaKey) serialize(w io.Writer) (err error) { 74 buf := make([]byte, maxOIDLength+1) 75 buf[0] = byte(len(f.oid)) 76 copy(buf[1:], f.oid) 77 if _, err = w.Write(buf[:len(f.oid)+1]); err != nil { 78 return 79 } 80 return writeMPIs(w, f.p) 81} 82 83func (f *ecdsaKey) newECDSA() (*ecdsa.PublicKey, error) { 84 var c elliptic.Curve 85 if bytes.Equal(f.oid, oidCurveP256) { 86 c = elliptic.P256() 87 } else if bytes.Equal(f.oid, oidCurveP384) { 88 c = elliptic.P384() 89 } else if bytes.Equal(f.oid, oidCurveP521) { 90 c = elliptic.P521() 91 } else { 92 return nil, errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", f.oid)) 93 } 94 x, y := elliptic.Unmarshal(c, f.p.bytes) 95 if x == nil { 96 return nil, errors.UnsupportedError("failed to parse EC point") 97 } 98 return &ecdsa.PublicKey{Curve: c, X: x, Y: y}, nil 99} 100 101func (f *ecdsaKey) byteLen() int { 102 return 1 + len(f.oid) + 2 + len(f.p.bytes) 103} 104 105type kdfHashFunction byte 106type kdfAlgorithm byte 107 108// ecdhKdf stores key derivation function parameters 109// used for ECDH encryption. See RFC 6637, Section 9. 110type ecdhKdf struct { 111 KdfHash kdfHashFunction 112 KdfAlgo kdfAlgorithm 113} 114 115func (f *ecdhKdf) parse(r io.Reader) (err error) { 116 buf := make([]byte, 1) 117 if _, err = readFull(r, buf); err != nil { 118 return 119 } 120 kdfLen := int(buf[0]) 121 if kdfLen < 3 { 122 return errors.UnsupportedError("Unsupported ECDH KDF length: " + strconv.Itoa(kdfLen)) 123 } 124 buf = make([]byte, kdfLen) 125 if _, err = readFull(r, buf); err != nil { 126 return 127 } 128 reserved := int(buf[0]) 129 f.KdfHash = kdfHashFunction(buf[1]) 130 f.KdfAlgo = kdfAlgorithm(buf[2]) 131 if reserved != 0x01 { 132 return errors.UnsupportedError("Unsupported KDF reserved field: " + strconv.Itoa(reserved)) 133 } 134 return 135} 136 137func (f *ecdhKdf) serialize(w io.Writer) (err error) { 138 buf := make([]byte, 4) 139 // See RFC 6637, Section 9, Algorithm-Specific Fields for ECDH keys. 140 buf[0] = byte(0x03) // Length of the following fields 141 buf[1] = byte(0x01) // Reserved for future extensions, must be 1 for now 142 buf[2] = byte(f.KdfHash) 143 buf[3] = byte(f.KdfAlgo) 144 _, err = w.Write(buf[:]) 145 return 146} 147 148func (f *ecdhKdf) byteLen() int { 149 return 4 150} 151 152// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2. 153type PublicKey struct { 154 CreationTime time.Time 155 PubKeyAlgo PublicKeyAlgorithm 156 PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey or *ecdsa.PublicKey 157 Fingerprint [20]byte 158 KeyId uint64 159 IsSubkey bool 160 161 n, e, p, q, g, y parsedMPI 162 163 // RFC 6637 fields 164 ec *ecdsaKey 165 ecdh *ecdhKdf 166} 167 168// signingKey provides a convenient abstraction over signature verification 169// for v3 and v4 public keys. 170type signingKey interface { 171 SerializeSignaturePrefix(io.Writer) 172 serializeWithoutHeaders(io.Writer) error 173} 174 175func fromBig(n *big.Int) parsedMPI { 176 return parsedMPI{ 177 bytes: n.Bytes(), 178 bitLength: uint16(n.BitLen()), 179 } 180} 181 182// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey. 183func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey { 184 pk := &PublicKey{ 185 CreationTime: creationTime, 186 PubKeyAlgo: PubKeyAlgoRSA, 187 PublicKey: pub, 188 n: fromBig(pub.N), 189 e: fromBig(big.NewInt(int64(pub.E))), 190 } 191 192 pk.setFingerPrintAndKeyId() 193 return pk 194} 195 196// NewDSAPublicKey returns a PublicKey that wraps the given dsa.PublicKey. 197func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey { 198 pk := &PublicKey{ 199 CreationTime: creationTime, 200 PubKeyAlgo: PubKeyAlgoDSA, 201 PublicKey: pub, 202 p: fromBig(pub.P), 203 q: fromBig(pub.Q), 204 g: fromBig(pub.G), 205 y: fromBig(pub.Y), 206 } 207 208 pk.setFingerPrintAndKeyId() 209 return pk 210} 211 212// NewElGamalPublicKey returns a PublicKey that wraps the given elgamal.PublicKey. 213func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *PublicKey { 214 pk := &PublicKey{ 215 CreationTime: creationTime, 216 PubKeyAlgo: PubKeyAlgoElGamal, 217 PublicKey: pub, 218 p: fromBig(pub.P), 219 g: fromBig(pub.G), 220 y: fromBig(pub.Y), 221 } 222 223 pk.setFingerPrintAndKeyId() 224 return pk 225} 226 227func (pk *PublicKey) parse(r io.Reader) (err error) { 228 // RFC 4880, section 5.5.2 229 var buf [6]byte 230 _, err = readFull(r, buf[:]) 231 if err != nil { 232 return 233 } 234 if buf[0] != 4 { 235 return errors.UnsupportedError("public key version") 236 } 237 pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0) 238 pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5]) 239 switch pk.PubKeyAlgo { 240 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: 241 err = pk.parseRSA(r) 242 case PubKeyAlgoDSA: 243 err = pk.parseDSA(r) 244 case PubKeyAlgoElGamal: 245 err = pk.parseElGamal(r) 246 case PubKeyAlgoECDSA: 247 pk.ec = new(ecdsaKey) 248 if err = pk.ec.parse(r); err != nil { 249 return err 250 } 251 pk.PublicKey, err = pk.ec.newECDSA() 252 case PubKeyAlgoECDH: 253 pk.ec = new(ecdsaKey) 254 if err = pk.ec.parse(r); err != nil { 255 return 256 } 257 pk.ecdh = new(ecdhKdf) 258 if err = pk.ecdh.parse(r); err != nil { 259 return 260 } 261 // The ECDH key is stored in an ecdsa.PublicKey for convenience. 262 pk.PublicKey, err = pk.ec.newECDSA() 263 default: 264 err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo))) 265 } 266 if err != nil { 267 return 268 } 269 270 pk.setFingerPrintAndKeyId() 271 return 272} 273 274func (pk *PublicKey) setFingerPrintAndKeyId() { 275 // RFC 4880, section 12.2 276 fingerPrint := sha1.New() 277 pk.SerializeSignaturePrefix(fingerPrint) 278 pk.serializeWithoutHeaders(fingerPrint) 279 copy(pk.Fingerprint[:], fingerPrint.Sum(nil)) 280 pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20]) 281} 282 283// parseRSA parses RSA public key material from the given Reader. See RFC 4880, 284// section 5.5.2. 285func (pk *PublicKey) parseRSA(r io.Reader) (err error) { 286 pk.n.bytes, pk.n.bitLength, err = readMPI(r) 287 if err != nil { 288 return 289 } 290 pk.e.bytes, pk.e.bitLength, err = readMPI(r) 291 if err != nil { 292 return 293 } 294 295 if len(pk.e.bytes) > 3 { 296 err = errors.UnsupportedError("large public exponent") 297 return 298 } 299 rsa := &rsa.PublicKey{ 300 N: new(big.Int).SetBytes(pk.n.bytes), 301 E: 0, 302 } 303 for i := 0; i < len(pk.e.bytes); i++ { 304 rsa.E <<= 8 305 rsa.E |= int(pk.e.bytes[i]) 306 } 307 pk.PublicKey = rsa 308 return 309} 310 311// parseDSA parses DSA public key material from the given Reader. See RFC 4880, 312// section 5.5.2. 313func (pk *PublicKey) parseDSA(r io.Reader) (err error) { 314 pk.p.bytes, pk.p.bitLength, err = readMPI(r) 315 if err != nil { 316 return 317 } 318 pk.q.bytes, pk.q.bitLength, err = readMPI(r) 319 if err != nil { 320 return 321 } 322 pk.g.bytes, pk.g.bitLength, err = readMPI(r) 323 if err != nil { 324 return 325 } 326 pk.y.bytes, pk.y.bitLength, err = readMPI(r) 327 if err != nil { 328 return 329 } 330 331 dsa := new(dsa.PublicKey) 332 dsa.P = new(big.Int).SetBytes(pk.p.bytes) 333 dsa.Q = new(big.Int).SetBytes(pk.q.bytes) 334 dsa.G = new(big.Int).SetBytes(pk.g.bytes) 335 dsa.Y = new(big.Int).SetBytes(pk.y.bytes) 336 pk.PublicKey = dsa 337 return 338} 339 340// parseElGamal parses ElGamal public key material from the given Reader. See 341// RFC 4880, section 5.5.2. 342func (pk *PublicKey) parseElGamal(r io.Reader) (err error) { 343 pk.p.bytes, pk.p.bitLength, err = readMPI(r) 344 if err != nil { 345 return 346 } 347 pk.g.bytes, pk.g.bitLength, err = readMPI(r) 348 if err != nil { 349 return 350 } 351 pk.y.bytes, pk.y.bitLength, err = readMPI(r) 352 if err != nil { 353 return 354 } 355 356 elgamal := new(elgamal.PublicKey) 357 elgamal.P = new(big.Int).SetBytes(pk.p.bytes) 358 elgamal.G = new(big.Int).SetBytes(pk.g.bytes) 359 elgamal.Y = new(big.Int).SetBytes(pk.y.bytes) 360 pk.PublicKey = elgamal 361 return 362} 363 364// SerializeSignaturePrefix writes the prefix for this public key to the given Writer. 365// The prefix is used when calculating a signature over this public key. See 366// RFC 4880, section 5.2.4. 367func (pk *PublicKey) SerializeSignaturePrefix(h io.Writer) { 368 var pLength uint16 369 switch pk.PubKeyAlgo { 370 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: 371 pLength += 2 + uint16(len(pk.n.bytes)) 372 pLength += 2 + uint16(len(pk.e.bytes)) 373 case PubKeyAlgoDSA: 374 pLength += 2 + uint16(len(pk.p.bytes)) 375 pLength += 2 + uint16(len(pk.q.bytes)) 376 pLength += 2 + uint16(len(pk.g.bytes)) 377 pLength += 2 + uint16(len(pk.y.bytes)) 378 case PubKeyAlgoElGamal: 379 pLength += 2 + uint16(len(pk.p.bytes)) 380 pLength += 2 + uint16(len(pk.g.bytes)) 381 pLength += 2 + uint16(len(pk.y.bytes)) 382 case PubKeyAlgoECDSA: 383 pLength += uint16(pk.ec.byteLen()) 384 case PubKeyAlgoECDH: 385 pLength += uint16(pk.ec.byteLen()) 386 pLength += uint16(pk.ecdh.byteLen()) 387 default: 388 panic("unknown public key algorithm") 389 } 390 pLength += 6 391 h.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}) 392 return 393} 394 395func (pk *PublicKey) Serialize(w io.Writer) (err error) { 396 length := 6 // 6 byte header 397 398 switch pk.PubKeyAlgo { 399 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: 400 length += 2 + len(pk.n.bytes) 401 length += 2 + len(pk.e.bytes) 402 case PubKeyAlgoDSA: 403 length += 2 + len(pk.p.bytes) 404 length += 2 + len(pk.q.bytes) 405 length += 2 + len(pk.g.bytes) 406 length += 2 + len(pk.y.bytes) 407 case PubKeyAlgoElGamal: 408 length += 2 + len(pk.p.bytes) 409 length += 2 + len(pk.g.bytes) 410 length += 2 + len(pk.y.bytes) 411 case PubKeyAlgoECDSA: 412 length += pk.ec.byteLen() 413 case PubKeyAlgoECDH: 414 length += pk.ec.byteLen() 415 length += pk.ecdh.byteLen() 416 default: 417 panic("unknown public key algorithm") 418 } 419 420 packetType := packetTypePublicKey 421 if pk.IsSubkey { 422 packetType = packetTypePublicSubkey 423 } 424 err = serializeHeader(w, packetType, length) 425 if err != nil { 426 return 427 } 428 return pk.serializeWithoutHeaders(w) 429} 430 431// serializeWithoutHeaders marshals the PublicKey to w in the form of an 432// OpenPGP public key packet, not including the packet header. 433func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) { 434 var buf [6]byte 435 buf[0] = 4 436 t := uint32(pk.CreationTime.Unix()) 437 buf[1] = byte(t >> 24) 438 buf[2] = byte(t >> 16) 439 buf[3] = byte(t >> 8) 440 buf[4] = byte(t) 441 buf[5] = byte(pk.PubKeyAlgo) 442 443 _, err = w.Write(buf[:]) 444 if err != nil { 445 return 446 } 447 448 switch pk.PubKeyAlgo { 449 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: 450 return writeMPIs(w, pk.n, pk.e) 451 case PubKeyAlgoDSA: 452 return writeMPIs(w, pk.p, pk.q, pk.g, pk.y) 453 case PubKeyAlgoElGamal: 454 return writeMPIs(w, pk.p, pk.g, pk.y) 455 case PubKeyAlgoECDSA: 456 return pk.ec.serialize(w) 457 case PubKeyAlgoECDH: 458 if err = pk.ec.serialize(w); err != nil { 459 return 460 } 461 return pk.ecdh.serialize(w) 462 } 463 return errors.InvalidArgumentError("bad public-key algorithm") 464} 465 466// CanSign returns true iff this public key can generate signatures 467func (pk *PublicKey) CanSign() bool { 468 return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal 469} 470 471// VerifySignature returns nil iff sig is a valid signature, made by this 472// public key, of the data hashed into signed. signed is mutated by this call. 473func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) { 474 if !pk.CanSign() { 475 return errors.InvalidArgumentError("public key cannot generate signatures") 476 } 477 478 signed.Write(sig.HashSuffix) 479 hashBytes := signed.Sum(nil) 480 481 if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { 482 return errors.SignatureError("hash tag doesn't match") 483 } 484 485 if pk.PubKeyAlgo != sig.PubKeyAlgo { 486 return errors.InvalidArgumentError("public key and signature use different algorithms") 487 } 488 489 switch pk.PubKeyAlgo { 490 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: 491 rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey) 492 err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes) 493 if err != nil { 494 return errors.SignatureError("RSA verification failure") 495 } 496 return nil 497 case PubKeyAlgoDSA: 498 dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey) 499 // Need to truncate hashBytes to match FIPS 186-3 section 4.6. 500 subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8 501 if len(hashBytes) > subgroupSize { 502 hashBytes = hashBytes[:subgroupSize] 503 } 504 if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) { 505 return errors.SignatureError("DSA verification failure") 506 } 507 return nil 508 case PubKeyAlgoECDSA: 509 ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey) 510 if !ecdsa.Verify(ecdsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.ECDSASigR.bytes), new(big.Int).SetBytes(sig.ECDSASigS.bytes)) { 511 return errors.SignatureError("ECDSA verification failure") 512 } 513 return nil 514 default: 515 return errors.SignatureError("Unsupported public key algorithm used in signature") 516 } 517 panic("unreachable") 518} 519 520// VerifySignatureV3 returns nil iff sig is a valid signature, made by this 521// public key, of the data hashed into signed. signed is mutated by this call. 522func (pk *PublicKey) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) { 523 if !pk.CanSign() { 524 return errors.InvalidArgumentError("public key cannot generate signatures") 525 } 526 527 suffix := make([]byte, 5) 528 suffix[0] = byte(sig.SigType) 529 binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix())) 530 signed.Write(suffix) 531 hashBytes := signed.Sum(nil) 532 533 if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { 534 return errors.SignatureError("hash tag doesn't match") 535 } 536 537 if pk.PubKeyAlgo != sig.PubKeyAlgo { 538 return errors.InvalidArgumentError("public key and signature use different algorithms") 539 } 540 541 switch pk.PubKeyAlgo { 542 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: 543 rsaPublicKey := pk.PublicKey.(*rsa.PublicKey) 544 if err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil { 545 return errors.SignatureError("RSA verification failure") 546 } 547 return 548 case PubKeyAlgoDSA: 549 dsaPublicKey := pk.PublicKey.(*dsa.PublicKey) 550 // Need to truncate hashBytes to match FIPS 186-3 section 4.6. 551 subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8 552 if len(hashBytes) > subgroupSize { 553 hashBytes = hashBytes[:subgroupSize] 554 } 555 if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) { 556 return errors.SignatureError("DSA verification failure") 557 } 558 return nil 559 default: 560 panic("shouldn't happen") 561 } 562 panic("unreachable") 563} 564 565// keySignatureHash returns a Hash of the message that needs to be signed for 566// pk to assert a subkey relationship to signed. 567func keySignatureHash(pk, signed signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { 568 if !hashFunc.Available() { 569 return nil, errors.UnsupportedError("hash function") 570 } 571 h = hashFunc.New() 572 573 // RFC 4880, section 5.2.4 574 pk.SerializeSignaturePrefix(h) 575 pk.serializeWithoutHeaders(h) 576 signed.SerializeSignaturePrefix(h) 577 signed.serializeWithoutHeaders(h) 578 return 579} 580 581// VerifyKeySignature returns nil iff sig is a valid signature, made by this 582// public key, of signed. 583func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error { 584 h, err := keySignatureHash(pk, signed, sig.Hash) 585 if err != nil { 586 return err 587 } 588 if err = pk.VerifySignature(h, sig); err != nil { 589 return err 590 } 591 592 if sig.FlagSign { 593 // Signing subkeys must be cross-signed. See 594 // https://www.gnupg.org/faq/subkey-cross-certify.html. 595 if sig.EmbeddedSignature == nil { 596 return errors.StructuralError("signing subkey is missing cross-signature") 597 } 598 // Verify the cross-signature. This is calculated over the same 599 // data as the main signature, so we cannot just recursively 600 // call signed.VerifyKeySignature(...) 601 if h, err = keySignatureHash(pk, signed, sig.EmbeddedSignature.Hash); err != nil { 602 return errors.StructuralError("error while hashing for cross-signature: " + err.Error()) 603 } 604 if err := signed.VerifySignature(h, sig.EmbeddedSignature); err != nil { 605 return errors.StructuralError("error while verifying cross-signature: " + err.Error()) 606 } 607 } 608 609 return nil 610} 611 612func keyRevocationHash(pk signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { 613 if !hashFunc.Available() { 614 return nil, errors.UnsupportedError("hash function") 615 } 616 h = hashFunc.New() 617 618 // RFC 4880, section 5.2.4 619 pk.SerializeSignaturePrefix(h) 620 pk.serializeWithoutHeaders(h) 621 622 return 623} 624 625// VerifyRevocationSignature returns nil iff sig is a valid signature, made by this 626// public key. 627func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) { 628 h, err := keyRevocationHash(pk, sig.Hash) 629 if err != nil { 630 return err 631 } 632 return pk.VerifySignature(h, sig) 633} 634 635// userIdSignatureHash returns a Hash of the message that needs to be signed 636// to assert that pk is a valid key for id. 637func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash.Hash, err error) { 638 if !hashFunc.Available() { 639 return nil, errors.UnsupportedError("hash function") 640 } 641 h = hashFunc.New() 642 643 // RFC 4880, section 5.2.4 644 pk.SerializeSignaturePrefix(h) 645 pk.serializeWithoutHeaders(h) 646 647 var buf [5]byte 648 buf[0] = 0xb4 649 buf[1] = byte(len(id) >> 24) 650 buf[2] = byte(len(id) >> 16) 651 buf[3] = byte(len(id) >> 8) 652 buf[4] = byte(len(id)) 653 h.Write(buf[:]) 654 h.Write([]byte(id)) 655 656 return 657} 658 659// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this 660// public key, that id is the identity of pub. 661func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) { 662 h, err := userIdSignatureHash(id, pub, sig.Hash) 663 if err != nil { 664 return err 665 } 666 return pk.VerifySignature(h, sig) 667} 668 669// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this 670// public key, that id is the identity of pub. 671func (pk *PublicKey) VerifyUserIdSignatureV3(id string, pub *PublicKey, sig *SignatureV3) (err error) { 672 h, err := userIdSignatureV3Hash(id, pub, sig.Hash) 673 if err != nil { 674 return err 675 } 676 return pk.VerifySignatureV3(h, sig) 677} 678 679// KeyIdString returns the public key's fingerprint in capital hex 680// (e.g. "6C7EE1B8621CC013"). 681func (pk *PublicKey) KeyIdString() string { 682 return fmt.Sprintf("%X", pk.Fingerprint[12:20]) 683} 684 685// KeyIdShortString returns the short form of public key's fingerprint 686// in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). 687func (pk *PublicKey) KeyIdShortString() string { 688 return fmt.Sprintf("%X", pk.Fingerprint[16:20]) 689} 690 691// A parsedMPI is used to store the contents of a big integer, along with the 692// bit length that was specified in the original input. This allows the MPI to 693// be reserialized exactly. 694type parsedMPI struct { 695 bytes []byte 696 bitLength uint16 697} 698 699// writeMPIs is a utility function for serializing several big integers to the 700// given Writer. 701func writeMPIs(w io.Writer, mpis ...parsedMPI) (err error) { 702 for _, mpi := range mpis { 703 err = writeMPI(w, mpi.bitLength, mpi.bytes) 704 if err != nil { 705 return 706 } 707 } 708 return 709} 710 711// BitLength returns the bit length for the given public key. 712func (pk *PublicKey) BitLength() (bitLength uint16, err error) { 713 switch pk.PubKeyAlgo { 714 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: 715 bitLength = pk.n.bitLength 716 case PubKeyAlgoDSA: 717 bitLength = pk.p.bitLength 718 case PubKeyAlgoElGamal: 719 bitLength = pk.p.bitLength 720 default: 721 err = errors.InvalidArgumentError("bad public-key algorithm") 722 } 723 return 724} 725