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 "crypto" 9 "crypto/dsa" 10 "crypto/ecdsa" 11 "crypto/elliptic" 12 "crypto/rsa" 13 "crypto/sha1" 14 "crypto/sha256" 15 _ "crypto/sha512" 16 "encoding/binary" 17 "fmt" 18 "hash" 19 "io" 20 "math/big" 21 "strconv" 22 "time" 23 24 "github.com/ProtonMail/go-crypto/openpgp/ecdh" 25 "github.com/ProtonMail/go-crypto/openpgp/elgamal" 26 "github.com/ProtonMail/go-crypto/openpgp/errors" 27 "github.com/ProtonMail/go-crypto/openpgp/internal/algorithm" 28 "github.com/ProtonMail/go-crypto/openpgp/internal/ecc" 29 "github.com/ProtonMail/go-crypto/openpgp/internal/encoding" 30 "golang.org/x/crypto/ed25519" 31) 32 33type kdfHashFunction byte 34type kdfAlgorithm byte 35 36// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2. 37type PublicKey struct { 38 Version int 39 CreationTime time.Time 40 PubKeyAlgo PublicKeyAlgorithm 41 PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey or *eddsa.PublicKey 42 Fingerprint []byte 43 KeyId uint64 44 IsSubkey bool 45 46 // RFC 4880 fields 47 n, e, p, q, g, y encoding.Field 48 49 // RFC 6637 fields 50 // oid contains the OID byte sequence identifying the elliptic curve used 51 oid encoding.Field 52 53 // kdf stores key derivation function parameters 54 // used for ECDH encryption. See RFC 6637, Section 9. 55 kdf encoding.Field 56} 57 58// UpgradeToV5 updates the version of the key to v5, and updates all necessary 59// fields. 60func (pk *PublicKey) UpgradeToV5() { 61 pk.Version = 5 62 pk.setFingerprintAndKeyId() 63} 64 65// signingKey provides a convenient abstraction over signature verification 66// for v3 and v4 public keys. 67type signingKey interface { 68 SerializeForHash(io.Writer) error 69 SerializeSignaturePrefix(io.Writer) 70 serializeWithoutHeaders(io.Writer) error 71} 72 73// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey. 74func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey { 75 pk := &PublicKey{ 76 Version: 4, 77 CreationTime: creationTime, 78 PubKeyAlgo: PubKeyAlgoRSA, 79 PublicKey: pub, 80 n: new(encoding.MPI).SetBig(pub.N), 81 e: new(encoding.MPI).SetBig(big.NewInt(int64(pub.E))), 82 } 83 84 pk.setFingerprintAndKeyId() 85 return pk 86} 87 88// NewDSAPublicKey returns a PublicKey that wraps the given dsa.PublicKey. 89func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey { 90 pk := &PublicKey{ 91 Version: 4, 92 CreationTime: creationTime, 93 PubKeyAlgo: PubKeyAlgoDSA, 94 PublicKey: pub, 95 p: new(encoding.MPI).SetBig(pub.P), 96 q: new(encoding.MPI).SetBig(pub.Q), 97 g: new(encoding.MPI).SetBig(pub.G), 98 y: new(encoding.MPI).SetBig(pub.Y), 99 } 100 101 pk.setFingerprintAndKeyId() 102 return pk 103} 104 105// NewElGamalPublicKey returns a PublicKey that wraps the given elgamal.PublicKey. 106func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *PublicKey { 107 pk := &PublicKey{ 108 Version: 4, 109 CreationTime: creationTime, 110 PubKeyAlgo: PubKeyAlgoElGamal, 111 PublicKey: pub, 112 p: new(encoding.MPI).SetBig(pub.P), 113 g: new(encoding.MPI).SetBig(pub.G), 114 y: new(encoding.MPI).SetBig(pub.Y), 115 } 116 117 pk.setFingerprintAndKeyId() 118 return pk 119} 120 121func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey { 122 pk := &PublicKey{ 123 Version: 4, 124 CreationTime: creationTime, 125 PubKeyAlgo: PubKeyAlgoECDSA, 126 PublicKey: pub, 127 p: encoding.NewMPI(elliptic.Marshal(pub.Curve, pub.X, pub.Y)), 128 } 129 130 curveInfo := ecc.FindByCurve(pub.Curve) 131 if curveInfo == nil { 132 panic("unknown elliptic curve") 133 } 134 pk.oid = curveInfo.Oid 135 pk.setFingerprintAndKeyId() 136 return pk 137} 138 139func NewECDHPublicKey(creationTime time.Time, pub *ecdh.PublicKey) *PublicKey { 140 var pk *PublicKey 141 var curveInfo *ecc.CurveInfo 142 var kdf = encoding.NewOID([]byte{0x1, pub.Hash.Id(), pub.Cipher.Id()}) 143 if pub.CurveType == ecc.Curve25519 { 144 pk = &PublicKey{ 145 Version: 4, 146 CreationTime: creationTime, 147 PubKeyAlgo: PubKeyAlgoECDH, 148 PublicKey: pub, 149 p: encoding.NewMPI(pub.X.Bytes()), 150 kdf: kdf, 151 } 152 curveInfo = ecc.FindByName("Curve25519") 153 } else { 154 pk = &PublicKey{ 155 Version: 4, 156 CreationTime: creationTime, 157 PubKeyAlgo: PubKeyAlgoECDH, 158 PublicKey: pub, 159 p: encoding.NewMPI(elliptic.Marshal(pub.Curve, pub.X, pub.Y)), 160 kdf: kdf, 161 } 162 curveInfo = ecc.FindByCurve(pub.Curve) 163 } 164 if curveInfo == nil { 165 panic("unknown elliptic curve") 166 } 167 pk.oid = curveInfo.Oid 168 pk.setFingerprintAndKeyId() 169 return pk 170} 171 172func NewEdDSAPublicKey(creationTime time.Time, pub *ed25519.PublicKey) *PublicKey { 173 curveInfo := ecc.FindByName("Ed25519") 174 pk := &PublicKey{ 175 Version: 4, 176 CreationTime: creationTime, 177 PubKeyAlgo: PubKeyAlgoEdDSA, 178 PublicKey: pub, 179 oid: curveInfo.Oid, 180 // Native point format, see draft-koch-eddsa-for-openpgp-04, Appendix B 181 p: encoding.NewMPI(append([]byte{0x40}, *pub...)), 182 } 183 184 pk.setFingerprintAndKeyId() 185 return pk 186} 187 188func (pk *PublicKey) parse(r io.Reader) (err error) { 189 // RFC 4880, section 5.5.2 190 var buf [6]byte 191 _, err = readFull(r, buf[:]) 192 if err != nil { 193 return 194 } 195 if buf[0] != 4 && buf[0] != 5 { 196 return errors.UnsupportedError("public key version " + strconv.Itoa(int(buf[0]))) 197 } 198 199 pk.Version = int(buf[0]) 200 if pk.Version == 5 { 201 var n [4]byte 202 _, err = readFull(r, n[:]) 203 if err != nil { 204 return 205 } 206 } 207 pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0) 208 pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5]) 209 switch pk.PubKeyAlgo { 210 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: 211 err = pk.parseRSA(r) 212 case PubKeyAlgoDSA: 213 err = pk.parseDSA(r) 214 case PubKeyAlgoElGamal: 215 err = pk.parseElGamal(r) 216 case PubKeyAlgoECDSA: 217 err = pk.parseECDSA(r) 218 case PubKeyAlgoECDH: 219 err = pk.parseECDH(r) 220 case PubKeyAlgoEdDSA: 221 err = pk.parseEdDSA(r) 222 default: 223 err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo))) 224 } 225 if err != nil { 226 return 227 } 228 229 pk.setFingerprintAndKeyId() 230 return 231} 232 233func (pk *PublicKey) setFingerprintAndKeyId() { 234 // RFC 4880, section 12.2 235 if pk.Version == 5 { 236 fingerprint := sha256.New() 237 pk.SerializeForHash(fingerprint) 238 pk.Fingerprint = make([]byte, 32) 239 copy(pk.Fingerprint, fingerprint.Sum(nil)) 240 pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[:8]) 241 } else { 242 fingerprint := sha1.New() 243 pk.SerializeForHash(fingerprint) 244 pk.Fingerprint = make([]byte, 20) 245 copy(pk.Fingerprint, fingerprint.Sum(nil)) 246 pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20]) 247 } 248} 249 250// parseRSA parses RSA public key material from the given Reader. See RFC 4880, 251// section 5.5.2. 252func (pk *PublicKey) parseRSA(r io.Reader) (err error) { 253 pk.n = new(encoding.MPI) 254 if _, err = pk.n.ReadFrom(r); err != nil { 255 return 256 } 257 pk.e = new(encoding.MPI) 258 if _, err = pk.e.ReadFrom(r); err != nil { 259 return 260 } 261 262 if len(pk.e.Bytes()) > 3 { 263 err = errors.UnsupportedError("large public exponent") 264 return 265 } 266 rsa := &rsa.PublicKey{ 267 N: new(big.Int).SetBytes(pk.n.Bytes()), 268 E: 0, 269 } 270 for i := 0; i < len(pk.e.Bytes()); i++ { 271 rsa.E <<= 8 272 rsa.E |= int(pk.e.Bytes()[i]) 273 } 274 pk.PublicKey = rsa 275 return 276} 277 278// parseDSA parses DSA public key material from the given Reader. See RFC 4880, 279// section 5.5.2. 280func (pk *PublicKey) parseDSA(r io.Reader) (err error) { 281 pk.p = new(encoding.MPI) 282 if _, err = pk.p.ReadFrom(r); err != nil { 283 return 284 } 285 pk.q = new(encoding.MPI) 286 if _, err = pk.q.ReadFrom(r); err != nil { 287 return 288 } 289 pk.g = new(encoding.MPI) 290 if _, err = pk.g.ReadFrom(r); err != nil { 291 return 292 } 293 pk.y = new(encoding.MPI) 294 if _, err = pk.y.ReadFrom(r); err != nil { 295 return 296 } 297 298 dsa := new(dsa.PublicKey) 299 dsa.P = new(big.Int).SetBytes(pk.p.Bytes()) 300 dsa.Q = new(big.Int).SetBytes(pk.q.Bytes()) 301 dsa.G = new(big.Int).SetBytes(pk.g.Bytes()) 302 dsa.Y = new(big.Int).SetBytes(pk.y.Bytes()) 303 pk.PublicKey = dsa 304 return 305} 306 307// parseElGamal parses ElGamal public key material from the given Reader. See 308// RFC 4880, section 5.5.2. 309func (pk *PublicKey) parseElGamal(r io.Reader) (err error) { 310 pk.p = new(encoding.MPI) 311 if _, err = pk.p.ReadFrom(r); err != nil { 312 return 313 } 314 pk.g = new(encoding.MPI) 315 if _, err = pk.g.ReadFrom(r); err != nil { 316 return 317 } 318 pk.y = new(encoding.MPI) 319 if _, err = pk.y.ReadFrom(r); err != nil { 320 return 321 } 322 323 elgamal := new(elgamal.PublicKey) 324 elgamal.P = new(big.Int).SetBytes(pk.p.Bytes()) 325 elgamal.G = new(big.Int).SetBytes(pk.g.Bytes()) 326 elgamal.Y = new(big.Int).SetBytes(pk.y.Bytes()) 327 pk.PublicKey = elgamal 328 return 329} 330 331// parseECDSA parses ECDSA public key material from the given Reader. See 332// RFC 6637, Section 9. 333func (pk *PublicKey) parseECDSA(r io.Reader) (err error) { 334 pk.oid = new(encoding.OID) 335 if _, err = pk.oid.ReadFrom(r); err != nil { 336 return 337 } 338 pk.p = new(encoding.MPI) 339 if _, err = pk.p.ReadFrom(r); err != nil { 340 return 341 } 342 343 var c elliptic.Curve 344 curveInfo := ecc.FindByOid(pk.oid) 345 if curveInfo == nil || curveInfo.SigAlgorithm != ecc.ECDSA { 346 return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid)) 347 } 348 c = curveInfo.Curve 349 x, y := elliptic.Unmarshal(c, pk.p.Bytes()) 350 if x == nil { 351 return errors.UnsupportedError("failed to parse EC point") 352 } 353 pk.PublicKey = &ecdsa.PublicKey{Curve: c, X: x, Y: y} 354 return 355} 356 357// parseECDH parses ECDH public key material from the given Reader. See 358// RFC 6637, Section 9. 359func (pk *PublicKey) parseECDH(r io.Reader) (err error) { 360 pk.oid = new(encoding.OID) 361 if _, err = pk.oid.ReadFrom(r); err != nil { 362 return 363 } 364 pk.p = new(encoding.MPI) 365 if _, err = pk.p.ReadFrom(r); err != nil { 366 return 367 } 368 pk.kdf = new(encoding.OID) 369 if _, err = pk.kdf.ReadFrom(r); err != nil { 370 return 371 } 372 373 curveInfo := ecc.FindByOid(pk.oid) 374 if curveInfo == nil { 375 return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid)) 376 } 377 378 c := curveInfo.Curve 379 cType := curveInfo.CurveType 380 381 var x, y *big.Int 382 if cType == ecc.Curve25519 { 383 x = new(big.Int) 384 x.SetBytes(pk.p.Bytes()) 385 } else { 386 x, y = elliptic.Unmarshal(c, pk.p.Bytes()) 387 } 388 if x == nil { 389 return errors.UnsupportedError("failed to parse EC point") 390 } 391 392 if kdfLen := len(pk.kdf.Bytes()); kdfLen < 3 { 393 return errors.UnsupportedError("unsupported ECDH KDF length: " + strconv.Itoa(kdfLen)) 394 } 395 if reserved := pk.kdf.Bytes()[0]; reserved != 0x01 { 396 return errors.UnsupportedError("unsupported KDF reserved field: " + strconv.Itoa(int(reserved))) 397 } 398 kdfHash, ok := algorithm.HashById[pk.kdf.Bytes()[1]] 399 if !ok { 400 return errors.UnsupportedError("unsupported ECDH KDF hash: " + strconv.Itoa(int(pk.kdf.Bytes()[1]))) 401 } 402 kdfCipher, ok := algorithm.CipherById[pk.kdf.Bytes()[2]] 403 if !ok { 404 return errors.UnsupportedError("unsupported ECDH KDF cipher: " + strconv.Itoa(int(pk.kdf.Bytes()[2]))) 405 } 406 407 pk.PublicKey = &ecdh.PublicKey{ 408 CurveType: cType, 409 Curve: c, 410 X: x, 411 Y: y, 412 KDF: ecdh.KDF{ 413 Hash: kdfHash, 414 Cipher: kdfCipher, 415 }, 416 } 417 return 418} 419 420func (pk *PublicKey) parseEdDSA(r io.Reader) (err error) { 421 pk.oid = new(encoding.OID) 422 if _, err = pk.oid.ReadFrom(r); err != nil { 423 return 424 } 425 curveInfo := ecc.FindByOid(pk.oid) 426 if curveInfo == nil || curveInfo.SigAlgorithm != ecc.EdDSA { 427 return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid)) 428 } 429 pk.p = new(encoding.MPI) 430 if _, err = pk.p.ReadFrom(r); err != nil { 431 return 432 } 433 434 eddsa := make(ed25519.PublicKey, ed25519.PublicKeySize) 435 switch flag := pk.p.Bytes()[0]; flag { 436 case 0x04: 437 // TODO: see _grcy_ecc_eddsa_ensure_compact in grcypt 438 return errors.UnsupportedError("unsupported EdDSA compression: " + strconv.Itoa(int(flag))) 439 case 0x40: 440 copy(eddsa[:], pk.p.Bytes()[1:]) 441 default: 442 return errors.UnsupportedError("unsupported EdDSA compression: " + strconv.Itoa(int(flag))) 443 } 444 445 pk.PublicKey = &eddsa 446 return 447} 448 449// SerializeForHash serializes the PublicKey to w with the special packet 450// header format needed for hashing. 451func (pk *PublicKey) SerializeForHash(w io.Writer) error { 452 pk.SerializeSignaturePrefix(w) 453 return pk.serializeWithoutHeaders(w) 454} 455 456// SerializeSignaturePrefix writes the prefix for this public key to the given Writer. 457// The prefix is used when calculating a signature over this public key. See 458// RFC 4880, section 5.2.4. 459func (pk *PublicKey) SerializeSignaturePrefix(w io.Writer) { 460 var pLength = pk.algorithmSpecificByteCount() 461 if pk.Version == 5 { 462 pLength += 10 // version, timestamp (4), algorithm, key octet count (4). 463 w.Write([]byte{ 464 0x9A, 465 byte(pLength >> 24), 466 byte(pLength >> 16), 467 byte(pLength >> 8), 468 byte(pLength), 469 }) 470 return 471 } 472 pLength += 6 473 w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}) 474} 475 476func (pk *PublicKey) Serialize(w io.Writer) (err error) { 477 length := 6 // 6 byte header 478 length += pk.algorithmSpecificByteCount() 479 if pk.Version == 5 { 480 length += 4 // octet key count 481 } 482 packetType := packetTypePublicKey 483 if pk.IsSubkey { 484 packetType = packetTypePublicSubkey 485 } 486 err = serializeHeader(w, packetType, length) 487 if err != nil { 488 return 489 } 490 return pk.serializeWithoutHeaders(w) 491} 492 493func (pk *PublicKey) algorithmSpecificByteCount() int { 494 length := 0 495 switch pk.PubKeyAlgo { 496 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: 497 length += int(pk.n.EncodedLength()) 498 length += int(pk.e.EncodedLength()) 499 case PubKeyAlgoDSA: 500 length += int(pk.p.EncodedLength()) 501 length += int(pk.q.EncodedLength()) 502 length += int(pk.g.EncodedLength()) 503 length += int(pk.y.EncodedLength()) 504 case PubKeyAlgoElGamal: 505 length += int(pk.p.EncodedLength()) 506 length += int(pk.g.EncodedLength()) 507 length += int(pk.y.EncodedLength()) 508 case PubKeyAlgoECDSA: 509 length += int(pk.oid.EncodedLength()) 510 length += int(pk.p.EncodedLength()) 511 case PubKeyAlgoECDH: 512 length += int(pk.oid.EncodedLength()) 513 length += int(pk.p.EncodedLength()) 514 length += int(pk.kdf.EncodedLength()) 515 case PubKeyAlgoEdDSA: 516 length += int(pk.oid.EncodedLength()) 517 length += int(pk.p.EncodedLength()) 518 default: 519 panic("unknown public key algorithm") 520 } 521 return length 522} 523 524// serializeWithoutHeaders marshals the PublicKey to w in the form of an 525// OpenPGP public key packet, not including the packet header. 526func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) { 527 t := uint32(pk.CreationTime.Unix()) 528 if _, err = w.Write([]byte{ 529 byte(pk.Version), 530 byte(t >> 24), byte(t >> 16), byte(t >> 8), byte(t), 531 byte(pk.PubKeyAlgo), 532 }); err != nil { 533 return 534 } 535 536 if pk.Version == 5 { 537 n := pk.algorithmSpecificByteCount() 538 if _, err = w.Write([]byte{ 539 byte(n >> 24), byte(n >> 16), byte(n >> 8), byte(n), 540 }); err != nil { 541 return 542 } 543 } 544 545 switch pk.PubKeyAlgo { 546 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: 547 if _, err = w.Write(pk.n.EncodedBytes()); err != nil { 548 return 549 } 550 _, err = w.Write(pk.e.EncodedBytes()) 551 return 552 case PubKeyAlgoDSA: 553 if _, err = w.Write(pk.p.EncodedBytes()); err != nil { 554 return 555 } 556 if _, err = w.Write(pk.q.EncodedBytes()); err != nil { 557 return 558 } 559 if _, err = w.Write(pk.g.EncodedBytes()); err != nil { 560 return 561 } 562 _, err = w.Write(pk.y.EncodedBytes()) 563 return 564 case PubKeyAlgoElGamal: 565 if _, err = w.Write(pk.p.EncodedBytes()); err != nil { 566 return 567 } 568 if _, err = w.Write(pk.g.EncodedBytes()); err != nil { 569 return 570 } 571 _, err = w.Write(pk.y.EncodedBytes()) 572 return 573 case PubKeyAlgoECDSA: 574 if _, err = w.Write(pk.oid.EncodedBytes()); err != nil { 575 return 576 } 577 _, err = w.Write(pk.p.EncodedBytes()) 578 return 579 case PubKeyAlgoECDH: 580 if _, err = w.Write(pk.oid.EncodedBytes()); err != nil { 581 return 582 } 583 if _, err = w.Write(pk.p.EncodedBytes()); err != nil { 584 return 585 } 586 _, err = w.Write(pk.kdf.EncodedBytes()) 587 return 588 case PubKeyAlgoEdDSA: 589 if _, err = w.Write(pk.oid.EncodedBytes()); err != nil { 590 return 591 } 592 _, err = w.Write(pk.p.EncodedBytes()) 593 return 594 } 595 return errors.InvalidArgumentError("bad public-key algorithm") 596} 597 598// CanSign returns true iff this public key can generate signatures 599func (pk *PublicKey) CanSign() bool { 600 return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal && pk.PubKeyAlgo != PubKeyAlgoECDH 601} 602 603// VerifySignature returns nil iff sig is a valid signature, made by this 604// public key, of the data hashed into signed. signed is mutated by this call. 605func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) { 606 if !pk.CanSign() { 607 return errors.InvalidArgumentError("public key cannot generate signatures") 608 } 609 if sig.Version == 5 && (sig.SigType == 0x00 || sig.SigType == 0x01) { 610 sig.AddMetadataToHashSuffix() 611 } 612 signed.Write(sig.HashSuffix) 613 hashBytes := signed.Sum(nil) 614 if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { 615 return errors.SignatureError("hash tag doesn't match") 616 } 617 618 if pk.PubKeyAlgo != sig.PubKeyAlgo { 619 return errors.InvalidArgumentError("public key and signature use different algorithms") 620 } 621 622 switch pk.PubKeyAlgo { 623 case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: 624 rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey) 625 err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.Bytes())) 626 if err != nil { 627 return errors.SignatureError("RSA verification failure") 628 } 629 return nil 630 case PubKeyAlgoDSA: 631 dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey) 632 // Need to truncate hashBytes to match FIPS 186-3 section 4.6. 633 subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8 634 if len(hashBytes) > subgroupSize { 635 hashBytes = hashBytes[:subgroupSize] 636 } 637 if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.Bytes()), new(big.Int).SetBytes(sig.DSASigS.Bytes())) { 638 return errors.SignatureError("DSA verification failure") 639 } 640 return nil 641 case PubKeyAlgoECDSA: 642 ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey) 643 if !ecdsa.Verify(ecdsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.ECDSASigR.Bytes()), new(big.Int).SetBytes(sig.ECDSASigS.Bytes())) { 644 return errors.SignatureError("ECDSA verification failure") 645 } 646 return nil 647 case PubKeyAlgoEdDSA: 648 eddsaPublicKey := pk.PublicKey.(*ed25519.PublicKey) 649 650 sigR := sig.EdDSASigR.Bytes() 651 sigS := sig.EdDSASigS.Bytes() 652 653 eddsaSig := make([]byte, ed25519.SignatureSize) 654 copy(eddsaSig[32-len(sigR):32], sigR) 655 copy(eddsaSig[64-len(sigS):], sigS) 656 657 if !ed25519.Verify(*eddsaPublicKey, hashBytes, eddsaSig) { 658 return errors.SignatureError("EdDSA verification failure") 659 } 660 return nil 661 default: 662 return errors.SignatureError("Unsupported public key algorithm used in signature") 663 } 664} 665 666// keySignatureHash returns a Hash of the message that needs to be signed for 667// pk to assert a subkey relationship to signed. 668func keySignatureHash(pk, signed signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { 669 if !hashFunc.Available() { 670 return nil, errors.UnsupportedError("hash function") 671 } 672 h = hashFunc.New() 673 674 // RFC 4880, section 5.2.4 675 err = pk.SerializeForHash(h) 676 if err != nil { 677 return nil, err 678 } 679 680 err = signed.SerializeForHash(h) 681 return 682} 683 684// VerifyKeySignature returns nil iff sig is a valid signature, made by this 685// public key, of signed. 686func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error { 687 h, err := keySignatureHash(pk, signed, sig.Hash) 688 if err != nil { 689 return err 690 } 691 if err = pk.VerifySignature(h, sig); err != nil { 692 return err 693 } 694 695 if sig.FlagSign { 696 // Signing subkeys must be cross-signed. See 697 // https://www.gnupg.org/faq/subkey-cross-certify.html. 698 if sig.EmbeddedSignature == nil { 699 return errors.StructuralError("signing subkey is missing cross-signature") 700 } 701 // Verify the cross-signature. This is calculated over the same 702 // data as the main signature, so we cannot just recursively 703 // call signed.VerifyKeySignature(...) 704 if h, err = keySignatureHash(pk, signed, sig.EmbeddedSignature.Hash); err != nil { 705 return errors.StructuralError("error while hashing for cross-signature: " + err.Error()) 706 } 707 if err := signed.VerifySignature(h, sig.EmbeddedSignature); err != nil { 708 return errors.StructuralError("error while verifying cross-signature: " + err.Error()) 709 } 710 } 711 712 return nil 713} 714 715func keyRevocationHash(pk signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { 716 if !hashFunc.Available() { 717 return nil, errors.UnsupportedError("hash function") 718 } 719 h = hashFunc.New() 720 721 // RFC 4880, section 5.2.4 722 err = pk.SerializeForHash(h) 723 724 return 725} 726 727// VerifyRevocationSignature returns nil iff sig is a valid signature, made by this 728// public key. 729func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) { 730 h, err := keyRevocationHash(pk, sig.Hash) 731 if err != nil { 732 return err 733 } 734 return pk.VerifySignature(h, sig) 735} 736 737// VerifySubkeyRevocationSignature returns nil iff sig is a valid subkey revocation signature, 738// made by the passed in signingKey. 739func (pk *PublicKey) VerifySubkeyRevocationSignature(sig *Signature, signingKey *PublicKey) (err error) { 740 h, err := keyRevocationHash(pk, sig.Hash) 741 if err != nil { 742 return err 743 } 744 return signingKey.VerifySignature(h, sig) 745} 746 747// userIdSignatureHash returns a Hash of the message that needs to be signed 748// to assert that pk is a valid key for id. 749func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash.Hash, err error) { 750 if !hashFunc.Available() { 751 return nil, errors.UnsupportedError("hash function") 752 } 753 h = hashFunc.New() 754 755 // RFC 4880, section 5.2.4 756 pk.SerializeSignaturePrefix(h) 757 pk.serializeWithoutHeaders(h) 758 759 var buf [5]byte 760 buf[0] = 0xb4 761 buf[1] = byte(len(id) >> 24) 762 buf[2] = byte(len(id) >> 16) 763 buf[3] = byte(len(id) >> 8) 764 buf[4] = byte(len(id)) 765 h.Write(buf[:]) 766 h.Write([]byte(id)) 767 768 return 769} 770 771// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this 772// public key, that id is the identity of pub. 773func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) { 774 h, err := userIdSignatureHash(id, pub, sig.Hash) 775 if err != nil { 776 return err 777 } 778 return pk.VerifySignature(h, sig) 779} 780 781// KeyIdString returns the public key's fingerprint in capital hex 782// (e.g. "6C7EE1B8621CC013"). 783func (pk *PublicKey) KeyIdString() string { 784 return fmt.Sprintf("%X", pk.Fingerprint[12:20]) 785} 786 787// KeyIdShortString returns the short form of public key's fingerprint 788// in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). 789func (pk *PublicKey) KeyIdShortString() string { 790 return fmt.Sprintf("%X", pk.Fingerprint[16:20]) 791} 792 793// BitLength returns the bit length for the given public key. 794func (pk *PublicKey) BitLength() (bitLength uint16, err error) { 795 switch pk.PubKeyAlgo { 796 case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: 797 bitLength = pk.n.BitLength() 798 case PubKeyAlgoDSA: 799 bitLength = pk.p.BitLength() 800 case PubKeyAlgoElGamal: 801 bitLength = pk.p.BitLength() 802 case PubKeyAlgoECDSA: 803 bitLength = pk.p.BitLength() 804 case PubKeyAlgoECDH: 805 bitLength = pk.p.BitLength() 806 case PubKeyAlgoEdDSA: 807 bitLength = pk.p.BitLength() 808 default: 809 err = errors.InvalidArgumentError("bad public-key algorithm") 810 } 811 return 812} 813 814// KeyExpired returns whether sig is a self-signature of a key that has 815// expired or is created in the future. 816func (pk *PublicKey) KeyExpired(sig *Signature, currentTime time.Time) bool { 817 if pk.CreationTime.After(currentTime) { 818 return true 819 } 820 if sig.KeyLifetimeSecs == nil || *sig.KeyLifetimeSecs == 0 { 821 return false 822 } 823 expiry := pk.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second) 824 return currentTime.After(expiry) 825} 826