Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse signature subpacket type 4 (exportable cert flag) #200

Merged
merged 7 commits into from
Apr 9, 2024
6 changes: 6 additions & 0 deletions openpgp/packet/signature.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ type signatureSubpacketType uint8
const (
creationTimeSubpacket signatureSubpacketType = 2
signatureExpirationSubpacket signatureSubpacketType = 3
exportableCertSubpacket signatureSubpacketType = 4
trustSubpacket signatureSubpacketType = 5
regularExpressionSubpacket signatureSubpacketType = 6
keyExpirationSubpacket signatureSubpacketType = 9
Expand Down Expand Up @@ -418,6 +419,11 @@ func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (r
}
sig.SigLifetimeSecs = new(uint32)
*sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket)
case exportableCertSubpacket:
if subpacket[0] == 0 {
err = errors.UnsupportedError("signature with non-exportable certification")
return
}
case trustSubpacket:
if len(subpacket) != 2 {
err = errors.StructuralError("trust subpacket with bad length")
Expand Down
27 changes: 27 additions & 0 deletions openpgp/packet/signature_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,29 @@ func TestSignatureWithTrustAndRegex(t *testing.T) {
}
}

func TestCanParseSignatureWithExportableCert(t *testing.T) {
packet, err := Read(readerFromHex(signatureWithExportableCertHex))
if err != nil {
t.Error(err)
return
}

_, ok := packet.(*Signature)
if !ok {
t.Errorf("failed to parse, got: %#v", packet)
}
}

func TestCannotParseSignatureWithNonExportableCert(t *testing.T) {
_, err := Read(readerFromHex(signatureWithNonExportableCertHex))
if err == nil {
t.Errorf("did not receive an error when expected")
}
if err.Error() != "openpgp: unsupported feature: signature with non-exportable certification" {
t.Errorf("unexpected error while parsing: %v", err)
}
}

const onePassSignatureDataHex = `c40d03000201ab105c91af38fb1501`

const signatureDataHex = "c2c05c04000102000605024cb45112000a0910ab105c91af38fb158f8d07ff5596ea368c5efe015bed6e78348c0f033c931d5f2ce5db54ce7f2a7e4b4ad64db758d65a7a71773edeab7ba2a9e0908e6a94a1175edd86c1d843279f045b021a6971a72702fcbd650efc393c5474d5b59a15f96d2eaad4c4c426797e0dcca2803ef41c6ff234d403eec38f31d610c344c06f2401c262f0993b2e66cad8a81ebc4322c723e0d4ba09fe917e8777658307ad8329adacba821420741009dfe87f007759f0982275d028a392c6ed983a0d846f890b36148c7358bdb8a516007fac760261ecd06076813831a36d0459075d1befa245ae7f7fb103d92ca759e9498fe60ef8078a39a3beda510deea251ea9f0a7f0df6ef42060f20780360686f3e400e"
Expand All @@ -335,3 +358,7 @@ const signatureWithTrustRegexHex = "c2bd0410010800310502886e09001621040f0bfb42b3
const signatureWithBadTrustRegexHex = "c2bc0410010800300502886e09001621040f0bfb42b3b08bece556fffcc181c053de849bf20385013c0e862a2e6578616d706c652e636f6d00007e7103fe3fa66963f7a91ceb297286f57bab38446ba591215a9d6589ab6ec0d930438a4d79f80a52440e017dc6dd03f7425ccc1e059edda2b32f4975501eacc5676f216e56c568b75442c3efc750425f0d5276c7611ef838ce3f015f4de0969b4710aac8a76fcf2d48dd0749e937099b55ab77d93132e9777ba3b8cf89f908c2dbfff838"

const positiveCertSignatureDataHex = "c2c0b304130108005d050b0908070206150a09080b020416020301021e010217802418686b70733a2f2f686b70732e706f6f6c2e736b732d6b6579736572766572732e6e65741621045ef9b8a44d89b32f94f3e9333679666422d0f62605025b2cc122021b2f000a09103679666422d0f62668e1080098b71f59ce893769ccb603344290e89df8f12d6ea906cc1c2b166c61a02679070744565f8280712b4e6bdfd482b758ef935655f1674c8f3633ab173d27cbe31e46368a8255134ecc5249ad66324cc4f6a79f160459b326711cfdc35032aac0903657a934f80f79768786ddd6554aa8d385c03adbee17c4e3e2831752d4910077da3b1f5562d267a57540a1c2b0dd2d96ed055c06098599b2390d61cfa37c6d19d9d63749fb3c3cfe0036fd959ba616eb23486216563fed8fdd19f96f5da9943db1698705fb688c1354c379ef01de307c4a0ac016e6385324cb0a7b49cfeee8961a289c8fa4c81d0e24e00969039db223a9835e8b86a8d85df645175f8aa0f8f2"

const signatureWithExportableCertHex = "c2c07404130102001e050263fde196050903c3b880021b26030b0309021601041508090a028401000a09101bf1d93a68a8b208342b07ff6f59f5a882d148c481b877b434271b2e844e0dd783d9eb5534aac51170024382089cf07194a1835c72177d677a7ce04a614c1f85ccf5972d08ebabdfefefbe9d0f2b9f0a0a010c0889d9ab43ec99ccaddf76f7a96d91c49256ae23078a22469fd2a3d1d2ccfb30eb4f137e8c893731163e8f7aa18abb6a72ebfbab71ac8946f991d0a10d0293bc275183f67567c709bdd7e035d16c3cb2d14565b8baccaf721a3e1ed59385fc4b248648bdf7072a07ed693caf9179ea980fa8f89bef9c6819870c0074aa0419bf80e073863fe4cfe144a3083586d05f3ce8277d891dc11aa157dd133ac8d2dab4e8095affe6f3d3be673d2392c9177102374f51c56199dd3c05"

const signatureWithNonExportableCertHex = "c2c07404130102001e050263fde196050903c3b880021b26030b0309021601041508090a028400000a09101bf1d93a68a8b208342b07ff6f59f5a882d148c481b877b434271b2e844e0dd783d9eb5534aac51170024382089cf07194a1835c72177d677a7ce04a614c1f85ccf5972d08ebabdfefefbe9d0f2b9f0a0a010c0889d9ab43ec99ccaddf76f7a96d91c49256ae23078a22469fd2a3d1d2ccfb30eb4f137e8c893731163e8f7aa18abb6a72ebfbab71ac8946f991d0a10d0293bc275183f67567c709bdd7e035d16c3cb2d14565b8baccaf721a3e1ed59385fc4b248648bdf7072a07ed693caf9179ea980fa8f89bef9c6819870c0074aa0419bf80e073863fe4cfe144a3083586d05f3ce8277d891dc11aa157dd133ac8d2dab4e8095affe6f3d3be673d2392c9177102374f51c56199dd3c05"
Loading