return
}
+// mpiLength returns the length of the given *big.Int when serialised as an
+// MPI.
+func mpiLength(n *big.Int) (mpiLengthInBytes int) {
+ mpiLengthInBytes = 2 /* MPI length */
+ mpiLengthInBytes += (n.BitLen() + 7) / 8
+ return
+}
+
// writeMPI serializes a big integer to w.
func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err os.Error) {
_, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)})
// RFC 4880, section 12.2
fingerPrint := sha1.New()
pk.SerializeSignaturePrefix(fingerPrint)
- pk.Serialize(fingerPrint)
+ pk.serializeWithoutHeaders(fingerPrint)
copy(pk.Fingerprint[:], fingerPrint.Sum())
pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20])
return
}
-// Serialize marshals the PublicKey to w in the form of an OpenPGP public key
-// packet, not including the packet header.
func (pk *PublicKey) Serialize(w io.Writer) (err os.Error) {
+ length := 6 // 6 byte header
+
+ switch pk.PubKeyAlgo {
+ case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
+ length += 2 + len(pk.n.bytes)
+ length += 2 + len(pk.e.bytes)
+ case PubKeyAlgoDSA:
+ length += 2 + len(pk.p.bytes)
+ length += 2 + len(pk.q.bytes)
+ length += 2 + len(pk.g.bytes)
+ length += 2 + len(pk.y.bytes)
+ }
+
+ err = serializeHeader(w, packetTypePublicKey, length)
+ if err != nil {
+ return
+ }
+ return pk.serializeWithoutHeaders(w)
+}
+
+// serializeWithoutHeaders marshals the PublicKey to w in the form of an
+// OpenPGP public key packet, not including the packet header.
+func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err os.Error) {
var buf [6]byte
buf[0] = 4
buf[1] = byte(pk.CreationTime >> 24)
// RFC 4880, section 5.2.4
pk.SerializeSignaturePrefix(h)
- pk.Serialize(h)
+ pk.serializeWithoutHeaders(h)
signed.SerializeSignaturePrefix(h)
- signed.Serialize(h)
+ signed.serializeWithoutHeaders(h)
return pk.VerifySignature(h, sig)
}
// RFC 4880, section 5.2.4
pk.SerializeSignaturePrefix(h)
- pk.Serialize(h)
+ pk.serializeWithoutHeaders(h)
var buf [5]byte
buf[0] = 0xb4
packet, err := Read(readerFromHex(test.hexData))
if err != nil {
t.Errorf("#%d: Read error: %s", i, err)
- return
+ continue
}
pk, ok := packet.(*PublicKey)
if !ok {
t.Errorf("#%d: failed to parse, got: %#v", i, packet)
- return
+ continue
}
if pk.PubKeyAlgo != test.pubKeyAlgo {
t.Errorf("#%d: bad public key algorithm got:%x want:%x", i, pk.PubKeyAlgo, test.pubKeyAlgo)
}
}
+func TestPublicKeySerialize(t *testing.T) {
+ for i, test := range pubKeyTests {
+ packet, err := Read(readerFromHex(test.hexData))
+ if err != nil {
+ t.Errorf("#%d: Read error: %s", i, err)
+ continue
+ }
+ pk, ok := packet.(*PublicKey)
+ if !ok {
+ t.Errorf("#%d: failed to parse, got: %#v", i, packet)
+ continue
+ }
+ serializeBuf := bytes.NewBuffer(nil)
+ err = pk.Serialize(serializeBuf)
+ if err != nil {
+ t.Errorf("#%d: failed to serialize: %s", err)
+ continue
+ }
+
+ packet, err = Read(serializeBuf)
+ if err != nil {
+ t.Errorf("#%d: Read error (from serialized data): %s", i, err)
+ continue
+ }
+ pk, ok = packet.(*PublicKey)
+ if !ok {
+ t.Errorf("#%d: failed to parse serialized data, got: %#v", i, packet)
+ continue
+ }
+ }
+}
+
const rsaFingerprintHex = "5fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb"
const rsaPkDataHex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001"
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
sigLength = len(sig.RSASignature)
case PubKeyAlgoDSA:
- sigLength = 2 /* MPI length */
- sigLength += (sig.DSASigR.BitLen() + 7) / 8
- sigLength += 2 /* MPI length */
- sigLength += (sig.DSASigS.BitLen() + 7) / 8
+ sigLength = mpiLength(sig.DSASigR)
+ sigLength += mpiLength(sig.DSASigS)
default:
panic("impossible")
}