Public key fingerprints.

This commit is contained in:
Brad Fitzpatrick 2010-12-07 16:59:24 -08:00
parent 0f16c9b29d
commit bfcc2ae8f5
1 changed files with 35 additions and 11 deletions

View File

@ -1,9 +1,11 @@
package packet package packet
import ( import (
"fmt"
"big" "big"
"crypto/openpgp/error" "crypto/openpgp/error"
"crypto/rsa" "crypto/rsa"
"crypto/sha1"
"io" "io"
"os" "os"
) )
@ -80,7 +82,7 @@ func ReadPacket(r io.Reader) (p Packet, err os.Error) {
case 2: case 2:
p, err = readSignaturePacket(limitReader) p, err = readSignaturePacket(limitReader)
case 6: case 6:
p, err = readPublicKeyPacket(limitReader) p, err = readPublicKeyPacket(limitReader, uint16(length))
default: default:
err = error.Unsupported("unknown packet type") err = error.Unsupported("unknown packet type")
} }
@ -195,17 +197,16 @@ func readSignaturePacket(r io.Reader) (sig SignaturePacket, err os.Error) {
} }
// We have already checked that the public key algorithm is RSA. // We have already checked that the public key algorithm is RSA.
sig.Signature, err = readMPI(r) sig.Signature, _, err = readMPI(r)
return return
} }
func readMPI(r io.Reader) (mpi []byte, err os.Error) { func readMPI(r io.Reader) (mpi []byte, hdr [2]byte, err os.Error) {
var buf [2]byte _, err = io.ReadFull(r, hdr[0:])
_, err = io.ReadFull(r, buf[0:])
if err != nil { if err != nil {
return return
} }
numBits := int(buf[0]) << 8 | int(buf[1]) numBits := int(hdr[0]) << 8 | int(hdr[1])
numBytes := (numBits + 7) / 8 numBytes := (numBits + 7) / 8
mpi = make([]byte, numBytes) mpi = make([]byte, numBytes)
_, err = io.ReadFull(r, mpi) _, err = io.ReadFull(r, mpi)
@ -291,15 +292,24 @@ func parseSignatureSubpacket(sig *SignaturePacket, subpacket []byte, isHashed bo
type PublicKeyPacket struct { type PublicKeyPacket struct {
CreationTime uint32 CreationTime uint32
PubKeyAlgo PublicKeyAlgorithm PubKeyAlgo PublicKeyAlgorithm
PublicKey rsa.PublicKey PublicKey rsa.PublicKey
Fingerprint []byte
} }
func (pk PublicKeyPacket) Type() string { func (pk PublicKeyPacket) Type() string {
return "public key" return "public key"
} }
func readPublicKeyPacket(r io.Reader) (pk PublicKeyPacket, err os.Error) { func (pk PublicKeyPacket) FingerprintString() string {
return fmt.Sprintf("%X", pk.Fingerprint)
}
func (pk PublicKeyPacket) KeyIdString() string {
return fmt.Sprintf("%X", pk.Fingerprint[len(pk.Fingerprint)-4:])
}
func readPublicKeyPacket(r io.Reader, length uint16) (pk PublicKeyPacket, err os.Error) {
// RFC 4880, section 5.5.2 // RFC 4880, section 5.5.2
var buf [6]byte var buf [6]byte
_, err = io.ReadFull(r, buf[0:]) _, err = io.ReadFull(r, buf[0:])
@ -309,6 +319,13 @@ func readPublicKeyPacket(r io.Reader) (pk PublicKeyPacket, err os.Error) {
if buf[0] != 4 { if buf[0] != 4 {
err = error.Unsupported("public key version") err = error.Unsupported("public key version")
} }
// RFC 4880, section 12.2
fprint := sha1.New()
fprint.Write([]byte{'\x99', uint8(length >> 8),
uint8(length & 0xff)})
fprint.Write(buf[0:6]) // version, timestamp, algorithm
pk.CreationTime = uint32(buf[1]) << 24 | pk.CreationTime = uint32(buf[1]) << 24 |
uint32(buf[2]) << 16 | uint32(buf[2]) << 16 |
uint32(buf[3]) << 8 | uint32(buf[3]) << 8 |
@ -320,14 +337,20 @@ func readPublicKeyPacket(r io.Reader) (pk PublicKeyPacket, err os.Error) {
err = error.Unsupported("public key type") err = error.Unsupported("public key type")
return return
} }
nBytes, err := readMPI(r)
nBytes, mpiHdr, err := readMPI(r)
if err != nil { if err != nil {
return return
} }
eBytes, err := readMPI(r) fprint.Write(mpiHdr[:])
fprint.Write(nBytes)
eBytes, mpiHdr, err := readMPI(r)
if err != nil { if err != nil {
return return
} }
fprint.Write(mpiHdr[:])
fprint.Write(eBytes)
if len(eBytes) > 3 { if len(eBytes) > 3 {
err = error.Unsupported("large public exponent") err = error.Unsupported("large public exponent")
@ -339,5 +362,6 @@ func readPublicKeyPacket(r io.Reader) (pk PublicKeyPacket, err os.Error) {
pk.PublicKey.E |= int(eBytes[i]) pk.PublicKey.E |= int(eBytes[i])
} }
pk.PublicKey.N = (new(big.Int)).SetBytes(nBytes) pk.PublicKey.N = (new(big.Int)).SetBytes(nBytes)
pk.Fingerprint = fprint.Sum()
return return
} }