aboutsummaryrefslogtreecommitdiff
path: root/x509util
diff options
context:
space:
mode:
Diffstat (limited to 'x509util')
-rw-r--r--x509util/x509util.go11
-rw-r--r--x509util/x509util_test.go155
2 files changed, 162 insertions, 4 deletions
diff --git a/x509util/x509util.go b/x509util/x509util.go
index 751aa29..f95b136 100644
--- a/x509util/x509util.go
+++ b/x509util/x509util.go
@@ -9,6 +9,7 @@ import (
"io/ioutil"
)
+// TODO: remove LoadCertificates
// LoadCertificates loads a PEM-encoded list of certificates from file
func LoadCertificates(path string) ([]*x509.Certificate, error) {
pem, err := ioutil.ReadFile(path)
@@ -18,6 +19,7 @@ func LoadCertificates(path string) ([]*x509.Certificate, error) {
return NewCertificateList(pem)
}
+// TODO: remove LoadTrustAnchors
// LoadTrustAnchors loads a list of PEM-encoded certificates from file
func LoadTrustAnchors(path string) ([]*x509.Certificate, *x509.CertPool, error) {
pem, err := ioutil.ReadFile(path)
@@ -31,6 +33,7 @@ func LoadTrustAnchors(path string) ([]*x509.Certificate, *x509.CertPool, error)
return anchorList, NewCertPool(anchorList), nil
}
+// TODO: remove LoadEd25519SigningKey
// LoadEd25519SigningKey loads an Ed25519 private key from a given path
func LoadEd25519SigningKey(path string) (ed25519.PrivateKey, error) {
data, err := ioutil.ReadFile(path)
@@ -47,7 +50,7 @@ func NewCertificateList(rest []byte) ([]*x509.Certificate, error) {
var block *pem.Block
block, rest = pem.Decode(rest)
if block == nil {
- break // TODO: fix such that new line in input is OK?
+ return nil, fmt.Errorf("no block: probably caused by leading white space")
}
if block.Type != "CERTIFICATE" {
return nil, fmt.Errorf("unexpected pem block type: %v", block.Type)
@@ -97,12 +100,12 @@ func NewEd25519PrivateKey(data []byte) (ed25519.PrivateKey, error) {
}
// ParseDerChain parses a list of DER-encoded X.509 certificates, such that the
-// first (zero-index) string is interpretted as an end-entity certificate and
-// the remaining ones as the an intermediate CertPool.
+// first (zero-index) blob is interpretted as an end-entity certificate and
+// the remaining ones as its intermediate CertPool.
func ParseDerChain(chain [][]byte) (*x509.Certificate, *x509.CertPool, error) {
certificates, err := ParseDerList(chain)
if err != nil || len(certificates) == 0 {
- return nil, nil, err
+ return nil, nil, err // TODO: don't think the len check works now..
}
intermediatePool := x509.NewCertPool()
for _, certificate := range certificates[1:] {
diff --git a/x509util/x509util_test.go b/x509util/x509util_test.go
new file mode 100644
index 0000000..772ff41
--- /dev/null
+++ b/x509util/x509util_test.go
@@ -0,0 +1,155 @@
+package x509util
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestNewEd25519PrivateKey(t *testing.T) {
+}
+
+func TestNewCertificateList(t *testing.T) {
+ for _, table := range []struct {
+ description string
+ pem []byte
+ wantErr bool
+ wantSerial []string
+ }{
+ {
+ description: "invalid block type",
+ pem: []byte(`-----BEGIN PRIVATE KEY-----
+MC4CAQAwBQYDK2VwBCIEIH65lXoCT4N9q4mPmDcsmAqIqG9CrqrB4KV2nqBC9JlZ
+-----END PRIVATE KEY-----`),
+ wantErr: true,
+ },
+ {
+ description: "bad block bytes: not a certificate",
+ pem: []byte(`-----BEGIN CERTIFICATE-----
+MC4CAQAwBQYDK2VwBCIEIH65lXoCT4N9q4mPmDcsmAqIqG9CrqrB4KV2nqBC9JlZ
+-----END CERTIFICATE-----`),
+ wantErr: true,
+ },
+ {
+ description: "bad block bytes: truncated certificate",
+ pem: []byte(`-----BEGIN CERTIFICATE-----
+MIIBbDCCAR4CFDfeuu6XURfn7AE4WShuwZBHEaLIMAUGAytlcDBsMQswCQYDVQQG
+-----END CERTIFICATE-----`),
+ wantErr: true,
+ },
+ {
+ description: "bad block bytes: truncated certificate in list",
+ pem: []byte(`-----BEGIN CERTIFICATE-----
+MIIBbDCCAR4CFDfeuu6XURfn7AE4WShuwZBHEaLIMAUGAytlcDBsMQswCQYDVQQG
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIB7jCCAaCgAwIBAgICEAAwBQYDK2VwMGwxCzAJBgNVBAYTAk5BMQswCQYDVQQI
+DAJOQTELMAkGA1UEBwwCTkExCzAJBgNVBAoMAk5BMQswCQYDVQQLDAJOQTEWMBQG
+A1UEAwwNc3RmZSB0ZXN0ZGF0YTERMA8GCSqGSIb3DQEJARYCTkEwHhcNMjAxMTAz
+MTgzMjE4WhcNMzIwMTIxMTgzMjE4WjBsMQswCQYDVQQGEwJOQTELMAkGA1UECAwC
+TkExCzAJBgNVBAcMAk5BMQswCQYDVQQKDAJOQTELMAkGA1UECwwCTkExFjAUBgNV
+BAMMDXN0ZmUgdGVzdGRhdGExETAPBgkqhkiG9w0BCQEWAk5BMCowBQYDK2VwAyEA
+F1yPPpjHKDAKN73pBFGXzAvIjdkLLimydu2y1HLMOiKjZjBkMB0GA1UdDgQWBBQ6
+P7JQ7yXtrTh7YkVU0I78P9A+nDAfBgNVHSMEGDAWgBQBvsxROtKU6zmr/SxcfTMD
+sAQcMTASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIChDAFBgMrZXAD
+QQBm1GMV0ADPnXRWnelCW9tcyTh0p9hKefuSy/MNx7/XLHKnM5fX+yHqD84QOxES
+Vc510vi4dM8I+e/vcoBsmMQP
+-----END CERTIFICATE-----`),
+ wantErr: true,
+ },
+ {
+ description: "bad block: unwanted white spaces",
+ pem: []byte(`
+ -----BEGIN CERTIFICATE-----
+ MIIBbDCCAR4CFDfeuu6XURfn7AE4WShuwZBHEaLIMAUGAytlcDBsMQswCQYDVQQG
+ EwJOQTELMAkGA1UECAwCTkExCzAJBgNVBAcMAk5BMQswCQYDVQQKDAJOQTELMAkG
+ A1UECwwCTkExFjAUBgNVBAMMDXN0ZmUgdGVzdGRhdGExETAPBgkqhkiG9w0BCQEW
+ Ak5BMB4XDTIwMTEwMzE4MzI0MFoXDTMyMDEyMTE4MzI0MFowRTELMAkGA1UEBhMC
+ QVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdp
+ dHMgUHR5IEx0ZDAqMAUGAytlcAMhAJvk390ZvwULplBri03Od4LLz+Sf/OUHu+20
+ wik+T9y5MAUGAytlcANBANekliXq4ttoClBJDZoktIQxyHHNcWyXFrj1HlOaT5bC
+ I3GIqqZ60Ua3jKytnEsKsD2rLMPItDwmG6wYSecy2ws=
+ -----END CERTIFICATE-----
+ `),
+ wantErr: true,
+ },
+ {
+ description: "ok certificate list: empty",
+ pem: []byte{},
+ wantSerial: nil,
+ },
+ {
+ description: "ok certificate list: size 1",
+ pem: []byte(`-----BEGIN CERTIFICATE-----
+MIIBbDCCAR4CFDfeuu6XURfn7AE4WShuwZBHEaLIMAUGAytlcDBsMQswCQYDVQQG
+EwJOQTELMAkGA1UECAwCTkExCzAJBgNVBAcMAk5BMQswCQYDVQQKDAJOQTELMAkG
+A1UECwwCTkExFjAUBgNVBAMMDXN0ZmUgdGVzdGRhdGExETAPBgkqhkiG9w0BCQEW
+Ak5BMB4XDTIwMTEwMzE4MzI0MFoXDTMyMDEyMTE4MzI0MFowRTELMAkGA1UEBhMC
+QVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdp
+dHMgUHR5IEx0ZDAqMAUGAytlcAMhAJvk390ZvwULplBri03Od4LLz+Sf/OUHu+20
+wik+T9y5MAUGAytlcANBANekliXq4ttoClBJDZoktIQxyHHNcWyXFrj1HlOaT5bC
+I3GIqqZ60Ua3jKytnEsKsD2rLMPItDwmG6wYSecy2ws=
+-----END CERTIFICATE-----`),
+ wantSerial: []string{
+ "318961541902906095038704399034602270237826065096",
+ },
+ },
+ {
+ description: "ok certificate list: size 2",
+ pem: []byte(`-----BEGIN CERTIFICATE-----
+MIIBbDCCAR4CFDfeuu6XURfn7AE4WShuwZBHEaLIMAUGAytlcDBsMQswCQYDVQQG
+EwJOQTELMAkGA1UECAwCTkExCzAJBgNVBAcMAk5BMQswCQYDVQQKDAJOQTELMAkG
+A1UECwwCTkExFjAUBgNVBAMMDXN0ZmUgdGVzdGRhdGExETAPBgkqhkiG9w0BCQEW
+Ak5BMB4XDTIwMTEwMzE4MzI0MFoXDTMyMDEyMTE4MzI0MFowRTELMAkGA1UEBhMC
+QVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdp
+dHMgUHR5IEx0ZDAqMAUGAytlcAMhAJvk390ZvwULplBri03Od4LLz+Sf/OUHu+20
+wik+T9y5MAUGAytlcANBANekliXq4ttoClBJDZoktIQxyHHNcWyXFrj1HlOaT5bC
+I3GIqqZ60Ua3jKytnEsKsD2rLMPItDwmG6wYSecy2ws=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIB7jCCAaCgAwIBAgICEAAwBQYDK2VwMGwxCzAJBgNVBAYTAk5BMQswCQYDVQQI
+DAJOQTELMAkGA1UEBwwCTkExCzAJBgNVBAoMAk5BMQswCQYDVQQLDAJOQTEWMBQG
+A1UEAwwNc3RmZSB0ZXN0ZGF0YTERMA8GCSqGSIb3DQEJARYCTkEwHhcNMjAxMTAz
+MTgzMjE4WhcNMzIwMTIxMTgzMjE4WjBsMQswCQYDVQQGEwJOQTELMAkGA1UECAwC
+TkExCzAJBgNVBAcMAk5BMQswCQYDVQQKDAJOQTELMAkGA1UECwwCTkExFjAUBgNV
+BAMMDXN0ZmUgdGVzdGRhdGExETAPBgkqhkiG9w0BCQEWAk5BMCowBQYDK2VwAyEA
+F1yPPpjHKDAKN73pBFGXzAvIjdkLLimydu2y1HLMOiKjZjBkMB0GA1UdDgQWBBQ6
+P7JQ7yXtrTh7YkVU0I78P9A+nDAfBgNVHSMEGDAWgBQBvsxROtKU6zmr/SxcfTMD
+sAQcMTASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIChDAFBgMrZXAD
+QQBm1GMV0ADPnXRWnelCW9tcyTh0p9hKefuSy/MNx7/XLHKnM5fX+yHqD84QOxES
+Vc510vi4dM8I+e/vcoBsmMQP
+-----END CERTIFICATE-----`),
+ wantSerial: []string{
+ "318961541902906095038704399034602270237826065096",
+ "4096",
+ },
+ },
+ } {
+ list, err := NewCertificateList(table.pem)
+ if got, want := err != nil, table.wantErr; got != want {
+ t.Errorf("got error=%v but wanted %v in test %q: %v", got, want, table.description, err)
+ }
+ if err != nil {
+ continue
+ }
+ if got, want := len(list), len(table.wantSerial); got != want {
+ t.Errorf("got list of length %d but wanted %d in test %q", got, want, table.description)
+ }
+ for i, certificate := range list {
+ if got, want := fmt.Sprintf("%v", certificate.SerialNumber), table.wantSerial[i]; got != want {
+ t.Errorf("Got serial number %s but wanted %s on index %d and test %q", got, want, i, table.description)
+ }
+ }
+ }
+}
+
+func TestNewCertPool(t *testing.T) {
+}
+
+func TestParseDerChain(t *testing.T) {
+}
+
+func TestParseDerList(t *testing.T) {
+}
+
+func TestVerifyChain(t *testing.T) {
+}