aboutsummaryrefslogtreecommitdiffstats
path: root/plumbing/object/signature_test.go
diff options
context:
space:
mode:
authorHidde Beydals <hidde@hhh.computer>2023-02-27 21:42:45 +0100
committerHidde Beydals <hidde@hhh.computer>2023-02-27 22:08:42 +0100
commitf1dc529fac28e6c45882292184270f94b5d30b7f (patch)
treec0ea214143dc9746dda0615422d7c7437aef395c /plumbing/object/signature_test.go
parent7ab4957732a817bada223e5c361f0c9753d9e40c (diff)
downloadgo-git-f1dc529fac28e6c45882292184270f94b5d30b7f.tar.gz
plumbing: support SSH/X509 signed tags
This commit enables support for extracting the SSH and X509 signatures from (annotated) Git tags, as an initial step to support the verification of more signatures than just PGP in go-git. The ported logic from Git further ensures that we look for a signature at the tail of an annotation, instead of the first signature we find in the annotation, as this could theoretically result in a faulty signature getting detected if part of a an annotation itself (e.g. by being placed in the middle as part of an inherited message). For commits, no further change is required as the current extraction of any signature (format) from `gpgsig` in the commit header is sufficient for manual verification. In a future iteration, we could add `signature/ssh` and `signature/x509` packages to further enable people to deal with verifying other signatures than PGP. As well as adding additional methods to `Commit` and `Tag` to provide glue between the packages and the most prominent user-facing APIs. Signed-off-by: Hidde Beydals <hidde@hhh.computer>
Diffstat (limited to 'plumbing/object/signature_test.go')
-rw-r--r--plumbing/object/signature_test.go180
1 files changed, 180 insertions, 0 deletions
diff --git a/plumbing/object/signature_test.go b/plumbing/object/signature_test.go
new file mode 100644
index 0000000..1bdb1d1
--- /dev/null
+++ b/plumbing/object/signature_test.go
@@ -0,0 +1,180 @@
+package object
+
+import (
+ "bytes"
+ "testing"
+)
+
+func Test_typeForSignature(t *testing.T) {
+ tests := []struct {
+ name string
+ b []byte
+ want signatureType
+ }{
+ {
+ name: "known signature format (PGP)",
+ b: []byte(`-----BEGIN PGP SIGNATURE-----
+
+iHUEABYKAB0WIQTMqU0ycQ3f6g3PMoWMmmmF4LuV8QUCYGebVwAKCRCMmmmF4LuV
+8VtyAP9LbuXAhtK6FQqOjKybBwlV70rLcXVP24ubDuz88VVwSgD+LuObsasWq6/U
+TssDKHUR2taa53bQYjkZQBpvvwOrLgc=
+=YQUf
+-----END PGP SIGNATURE-----`),
+ want: signatureTypeOpenPGP,
+ },
+ {
+ name: "known signature format (SSH)",
+ b: []byte(`-----BEGIN SSH SIGNATURE-----
+U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgij/EfHS8tCjolj5uEANXgKzFfp
+0D7wOhjWVbYZH6KugAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5
+AAAAQIYHMhSVV9L2xwJuV8eWMLjThya8yXgCHDzw3p01D19KirrabW0veiichPB5m+Ihtr
+MKEQruIQWJb+8HVXwssA4=
+-----END SSH SIGNATURE-----`),
+ want: signatureTypeSSH,
+ },
+ {
+ name: "known signature format (X509)",
+ b: []byte(`-----BEGIN CERTIFICATE-----
+MIIDZjCCAk6gAwIBAgIJALZ9Z3Z9Z3Z9MA0GCSqGSIb3DQEBCwUAMIGIMQswCQYD
+VQQGEwJTRTEOMAwGA1UECAwFVGV4YXMxDjAMBgNVBAcMBVRleGFzMQ4wDAYDVQQK
+DAVUZXhhczEOMAwGA1UECwwFVGV4YXMxGDAWBgNVBAMMD1RleGFzIENlcnRpZmlj
+YXRlMB4XDTE3MDUyNjE3MjY0MloXDTI3MDUyNDE3MjY0MlowgYgxCzAJBgNVBAYT
+AlNFMQ4wDAYDVQQIDAVUZXhhczEOMAwGA1UEBwwFVGV4YXMxDjAMBgNVBAoMBVRl
+eGFzMQ4wDAYDVQQLDAVUZXhhczEYMBYGA1UEAwwPVGV4YXMgQ2VydGlmaWNhdGUw
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDQZ9Z3Z9Z3Z9Z3Z9Z3Z9Z3
+-----END CERTIFICATE-----`),
+ want: signatureTypeX509,
+ },
+ {
+ name: "unknown signature format",
+ b: []byte(`-----BEGIN ARBITRARY SIGNATURE-----
+U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgij/EfHS8tCjolj5uEANXgKzFfp
+-----END UNKNOWN SIGNATURE-----`),
+ want: signatureTypeUnknown,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := typeForSignature(tt.b); got != tt.want {
+ t.Errorf("typeForSignature() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func Test_parseSignedBytes(t *testing.T) {
+ tests := []struct {
+ name string
+ b []byte
+ wantSignature []byte
+ wantType signatureType
+ }{
+ {
+ name: "detects signature and type",
+ b: []byte(`signed tag
+-----BEGIN PGP SIGNATURE-----
+
+iQGzBAABCAAdFiEE/h5sbbqJFh9j1AdUSqtFFGopTmwFAmB5XFkACgkQSqtFFGop
+TmxvgAv+IPjX5WCLFUIMx8hquMZp1VkhQrseE7rljUYaYpga8gZ9s4kseTGhy7Un
+61U3Ro6cTPEiQF/FkAGzSdPuGqv0ARBqHDX2tUI9+Zs/K8aG8tN+JTaof0gBcTyI
+BLbZVYDTxbS9whxSDewQd0OvBG1m9ISLUhjXo6mbaVvrKXNXTHg40MPZ8ZxjR/vN
+hxXXoUVnFyEDo+v6nK56mYtapThDaQQHHzD6D3VaCq3Msog7qAh9/ZNBmgb88aQ3
+FoK8PHMyr5elsV3mE9bciZBUc+dtzjOvp94uQ5ZKUXaPusXaYXnKpVnzhyer6RBI
+gJLWtPwAinqmN41rGJ8jDAGrpPNjaRrMhGtbyVUPUf19OxuUIroe77sIIKTP0X2o
+Wgp56dYpTst0JcGv/FYCeau/4pTRDfwHAOcDiBQ/0ag9IrZp9P8P9zlKmzNPEraV
+pAe1/EFuhv2UDLucAiWM8iDZIcw8iN0OYMOGUmnk0WuGIo7dzLeqMGY+ND5n5Z8J
+sZC//k6m
+=VhHy
+-----END PGP SIGNATURE-----`),
+ wantSignature: []byte(`-----BEGIN PGP SIGNATURE-----
+
+iQGzBAABCAAdFiEE/h5sbbqJFh9j1AdUSqtFFGopTmwFAmB5XFkACgkQSqtFFGop
+TmxvgAv+IPjX5WCLFUIMx8hquMZp1VkhQrseE7rljUYaYpga8gZ9s4kseTGhy7Un
+61U3Ro6cTPEiQF/FkAGzSdPuGqv0ARBqHDX2tUI9+Zs/K8aG8tN+JTaof0gBcTyI
+BLbZVYDTxbS9whxSDewQd0OvBG1m9ISLUhjXo6mbaVvrKXNXTHg40MPZ8ZxjR/vN
+hxXXoUVnFyEDo+v6nK56mYtapThDaQQHHzD6D3VaCq3Msog7qAh9/ZNBmgb88aQ3
+FoK8PHMyr5elsV3mE9bciZBUc+dtzjOvp94uQ5ZKUXaPusXaYXnKpVnzhyer6RBI
+gJLWtPwAinqmN41rGJ8jDAGrpPNjaRrMhGtbyVUPUf19OxuUIroe77sIIKTP0X2o
+Wgp56dYpTst0JcGv/FYCeau/4pTRDfwHAOcDiBQ/0ag9IrZp9P8P9zlKmzNPEraV
+pAe1/EFuhv2UDLucAiWM8iDZIcw8iN0OYMOGUmnk0WuGIo7dzLeqMGY+ND5n5Z8J
+sZC//k6m
+=VhHy
+-----END PGP SIGNATURE-----`),
+ wantType: signatureTypeOpenPGP,
+ },
+ {
+ name: "last signature for multiple signatures",
+ b: []byte(`signed tag
+-----BEGIN PGP SIGNATURE-----
+
+iQGzBAABCAAdFiEE/h5sbbqJFh9j1AdUSqtFFGopTmwFAmB5XFkACgkQSqtFFGop
+TmxvgAv+IPjX5WCLFUIMx8hquMZp1VkhQrseE7rljUYaYpga8gZ9s4kseTGhy7Un
+61U3Ro6cTPEiQF/FkAGzSdPuGqv0ARBqHDX2tUI9+Zs/K8aG8tN+JTaof0gBcTyI
+BLbZVYDTxbS9whxSDewQd0OvBG1m9ISLUhjXo6mbaVvrKXNXTHg40MPZ8ZxjR/vN
+hxXXoUVnFyEDo+v6nK56mYtapThDaQQHHzD6D3VaCq3Msog7qAh9/ZNBmgb88aQ3
+FoK8PHMyr5elsV3mE9bciZBUc+dtzjOvp94uQ5ZKUXaPusXaYXnKpVnzhyer6RBI
+gJLWtPwAinqmN41rGJ8jDAGrpPNjaRrMhGtbyVUPUf19OxuUIroe77sIIKTP0X2o
+Wgp56dYpTst0JcGv/FYCeau/4pTRDfwHAOcDiBQ/0ag9IrZp9P8P9zlKmzNPEraV
+pAe1/EFuhv2UDLucAiWM8iDZIcw8iN0OYMOGUmnk0WuGIo7dzLeqMGY+ND5n5Z8J
+sZC//k6m
+=VhHy
+-----END PGP SIGNATURE-----
+-----BEGIN SSH SIGNATURE-----
+U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgij/EfHS8tCjolj5uEANXgKzFfp
+0D7wOhjWVbYZH6KugAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5
+AAAAQIYHMhSVV9L2xwJuV8eWMLjThya8yXgCHDzw3p01D19KirrabW0veiichPB5m+Ihtr
+MKEQruIQWJb+8HVXwssA4=
+-----END SSH SIGNATURE-----`),
+ wantSignature: []byte(`-----BEGIN SSH SIGNATURE-----
+U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgij/EfHS8tCjolj5uEANXgKzFfp
+0D7wOhjWVbYZH6KugAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5
+AAAAQIYHMhSVV9L2xwJuV8eWMLjThya8yXgCHDzw3p01D19KirrabW0veiichPB5m+Ihtr
+MKEQruIQWJb+8HVXwssA4=
+-----END SSH SIGNATURE-----`),
+ wantType: signatureTypeSSH,
+ },
+ {
+ name: "signature with trailing data",
+ b: []byte(`An invalid
+
+-----BEGIN SSH SIGNATURE-----
+U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgij/EfHS8tCjolj5uEANXgKzFfp
+0D7wOhjWVbYZH6KugAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5
+AAAAQIYHMhSVV9L2xwJuV8eWMLjThya8yXgCHDzw3p01D19KirrabW0veiichPB5m+Ihtr
+MKEQruIQWJb+8HVXwssA4=
+-----END SSH SIGNATURE-----
+
+signed tag`),
+ wantSignature: []byte(`-----BEGIN SSH SIGNATURE-----
+U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgij/EfHS8tCjolj5uEANXgKzFfp
+0D7wOhjWVbYZH6KugAAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5
+AAAAQIYHMhSVV9L2xwJuV8eWMLjThya8yXgCHDzw3p01D19KirrabW0veiichPB5m+Ihtr
+MKEQruIQWJb+8HVXwssA4=
+-----END SSH SIGNATURE-----
+
+signed tag`),
+ wantType: signatureTypeSSH,
+ },
+ {
+ name: "data without signature",
+ b: []byte(`Some message`),
+ wantSignature: []byte(``),
+ wantType: signatureTypeUnknown,
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ pos, st := parseSignedBytes(tt.b)
+ var signature []byte
+ if pos >= 0 {
+ signature = tt.b[pos:]
+ }
+ if !bytes.Equal(signature, tt.wantSignature) {
+ t.Errorf("parseSignedBytes() got = %s for pos = %v, want %s", signature, pos, tt.wantSignature)
+ }
+ if st != tt.wantType {
+ t.Errorf("parseSignedBytes() got1 = %v, want %v", st, tt.wantType)
+ }
+ })
+ }
+}