summaryrefslogtreecommitdiffstats
path: root/jsonsign_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'jsonsign_test.go')
-rw-r--r--jsonsign_test.go380
1 files changed, 380 insertions, 0 deletions
diff --git a/jsonsign_test.go b/jsonsign_test.go
new file mode 100644
index 0000000..43e26ff
--- /dev/null
+++ b/jsonsign_test.go
@@ -0,0 +1,380 @@
+package libtrust
+
+import (
+ "bytes"
+ "crypto/rand"
+ "crypto/x509"
+ "encoding/json"
+ "fmt"
+ "io"
+ "testing"
+
+ "github.com/containers/libtrust/testutil"
+)
+
+func createTestJSON(sigKey string, indent string) (map[string]interface{}, []byte) {
+ testMap := map[string]interface{}{
+ "name": "dmcgowan/mycontainer",
+ "config": map[string]interface{}{
+ "ports": []int{9101, 9102},
+ "run": "/bin/echo \"Hello\"",
+ },
+ "layers": []string{
+ "2893c080-27f5-11e4-8c21-0800200c9a66",
+ "c54bc25b-fbb2-497b-a899-a8bc1b5b9d55",
+ "4d5d7e03-f908-49f3-a7f6-9ba28dfe0fb4",
+ "0b6da891-7f7f-4abf-9c97-7887549e696c",
+ "1d960389-ae4f-4011-85fd-18d0f96a67ad",
+ },
+ }
+ formattedSection := `{"config":{"ports":[9101,9102],"run":"/bin/echo \"Hello\""},"layers":["2893c080-27f5-11e4-8c21-0800200c9a66","c54bc25b-fbb2-497b-a899-a8bc1b5b9d55","4d5d7e03-f908-49f3-a7f6-9ba28dfe0fb4","0b6da891-7f7f-4abf-9c97-7887549e696c","1d960389-ae4f-4011-85fd-18d0f96a67ad"],"name":"dmcgowan/mycontainer","%s":[{"header":{`
+ formattedSection = fmt.Sprintf(formattedSection, sigKey)
+ if indent != "" {
+ buf := bytes.NewBuffer(nil)
+ json.Indent(buf, []byte(formattedSection), "", indent)
+ return testMap, buf.Bytes()
+ }
+ return testMap, []byte(formattedSection)
+
+}
+
+func TestSignJSON(t *testing.T) {
+ key, err := GenerateECP256PrivateKey()
+ if err != nil {
+ t.Fatalf("Error generating EC key: %s", err)
+ }
+
+ testMap, _ := createTestJSON("buildSignatures", " ")
+ indented, err := json.MarshalIndent(testMap, "", " ")
+ if err != nil {
+ t.Fatalf("Marshall error: %s", err)
+ }
+
+ js, err := NewJSONSignature(indented)
+ if err != nil {
+ t.Fatalf("Error creating JSON signature: %s", err)
+ }
+ err = js.Sign(key)
+ if err != nil {
+ t.Fatalf("Error signing content: %s", err)
+ }
+
+ keys, err := js.Verify()
+ if err != nil {
+ t.Fatalf("Error verifying signature: %s", err)
+ }
+ if len(keys) != 1 {
+ t.Fatalf("Error wrong number of keys returned")
+ }
+ if keys[0].KeyID() != key.KeyID() {
+ t.Fatalf("Unexpected public key returned")
+ }
+
+}
+
+func TestSignMap(t *testing.T) {
+ key, err := GenerateECP256PrivateKey()
+ if err != nil {
+ t.Fatalf("Error generating EC key: %s", err)
+ }
+
+ testMap, _ := createTestJSON("buildSignatures", " ")
+ js, err := NewJSONSignatureFromMap(testMap)
+ if err != nil {
+ t.Fatalf("Error creating JSON signature: %s", err)
+ }
+ err = js.Sign(key)
+ if err != nil {
+ t.Fatalf("Error signing JSON signature: %s", err)
+ }
+
+ keys, err := js.Verify()
+ if err != nil {
+ t.Fatalf("Error verifying signature: %s", err)
+ }
+ if len(keys) != 1 {
+ t.Fatalf("Error wrong number of keys returned")
+ }
+ if keys[0].KeyID() != key.KeyID() {
+ t.Fatalf("Unexpected public key returned")
+ }
+}
+
+func TestFormattedJson(t *testing.T) {
+ key, err := GenerateECP256PrivateKey()
+ if err != nil {
+ t.Fatalf("Error generating EC key: %s", err)
+ }
+
+ testMap, firstSection := createTestJSON("buildSignatures", " ")
+ indented, err := json.MarshalIndent(testMap, "", " ")
+ if err != nil {
+ t.Fatalf("Marshall error: %s", err)
+ }
+
+ js, err := NewJSONSignature(indented)
+ if err != nil {
+ t.Fatalf("Error creating JSON signature: %s", err)
+ }
+ err = js.Sign(key)
+ if err != nil {
+ t.Fatalf("Error signing content: %s", err)
+ }
+
+ b, err := js.PrettySignature("buildSignatures")
+ if err != nil {
+ t.Fatalf("Error signing map: %s", err)
+ }
+
+ if bytes.Compare(b[:len(firstSection)], firstSection) != 0 {
+ t.Fatalf("Wrong signed value\nExpected:\n%s\nActual:\n%s", firstSection, b[:len(firstSection)])
+ }
+
+ parsed, err := ParsePrettySignature(b, "buildSignatures")
+ if err != nil {
+ t.Fatalf("Error parsing formatted signature: %s", err)
+ }
+
+ keys, err := parsed.Verify()
+ if err != nil {
+ t.Fatalf("Error verifying signature: %s", err)
+ }
+ if len(keys) != 1 {
+ t.Fatalf("Error wrong number of keys returned")
+ }
+ if keys[0].KeyID() != key.KeyID() {
+ t.Fatalf("Unexpected public key returned")
+ }
+
+ var unmarshalled map[string]interface{}
+ err = json.Unmarshal(b, &unmarshalled)
+ if err != nil {
+ t.Fatalf("Could not unmarshall after parse: %s", err)
+ }
+
+}
+
+func TestFormattedFlatJson(t *testing.T) {
+ key, err := GenerateECP256PrivateKey()
+ if err != nil {
+ t.Fatalf("Error generating EC key: %s", err)
+ }
+
+ testMap, firstSection := createTestJSON("buildSignatures", "")
+ unindented, err := json.Marshal(testMap)
+ if err != nil {
+ t.Fatalf("Marshall error: %s", err)
+ }
+
+ js, err := NewJSONSignature(unindented)
+ if err != nil {
+ t.Fatalf("Error creating JSON signature: %s", err)
+ }
+ err = js.Sign(key)
+ if err != nil {
+ t.Fatalf("Error signing JSON signature: %s", err)
+ }
+
+ b, err := js.PrettySignature("buildSignatures")
+ if err != nil {
+ t.Fatalf("Error signing map: %s", err)
+ }
+
+ if bytes.Compare(b[:len(firstSection)], firstSection) != 0 {
+ t.Fatalf("Wrong signed value\nExpected:\n%s\nActual:\n%s", firstSection, b[:len(firstSection)])
+ }
+
+ parsed, err := ParsePrettySignature(b, "buildSignatures")
+ if err != nil {
+ t.Fatalf("Error parsing formatted signature: %s", err)
+ }
+
+ keys, err := parsed.Verify()
+ if err != nil {
+ t.Fatalf("Error verifying signature: %s", err)
+ }
+ if len(keys) != 1 {
+ t.Fatalf("Error wrong number of keys returned")
+ }
+ if keys[0].KeyID() != key.KeyID() {
+ t.Fatalf("Unexpected public key returned")
+ }
+}
+
+func generateTrustChain(t *testing.T, key PrivateKey, ca *x509.Certificate) (PrivateKey, []*x509.Certificate) {
+ parent := ca
+ parentKey := key
+ chain := make([]*x509.Certificate, 6)
+ for i := 5; i > 0; i-- {
+ intermediatekey, err := GenerateECP256PrivateKey()
+ if err != nil {
+ t.Fatalf("Error generate key: %s", err)
+ }
+ chain[i], err = testutil.GenerateIntermediate(intermediatekey.CryptoPublicKey(), parentKey.CryptoPrivateKey(), parent)
+ if err != nil {
+ t.Fatalf("Error generating intermdiate certificate: %s", err)
+ }
+ parent = chain[i]
+ parentKey = intermediatekey
+ }
+ trustKey, err := GenerateECP256PrivateKey()
+ if err != nil {
+ t.Fatalf("Error generate key: %s", err)
+ }
+ chain[0], err = testutil.GenerateTrustCert(trustKey.CryptoPublicKey(), parentKey.CryptoPrivateKey(), parent)
+ if err != nil {
+ t.Fatalf("Error generate trust cert: %s", err)
+ }
+
+ return trustKey, chain
+}
+
+func TestChainVerify(t *testing.T) {
+ caKey, err := GenerateECP256PrivateKey()
+ if err != nil {
+ t.Fatalf("Error generating key: %s", err)
+ }
+ ca, err := testutil.GenerateTrustCA(caKey.CryptoPublicKey(), caKey.CryptoPrivateKey())
+ if err != nil {
+ t.Fatalf("Error generating ca: %s", err)
+ }
+ trustKey, chain := generateTrustChain(t, caKey, ca)
+
+ testMap, _ := createTestJSON("verifySignatures", " ")
+ js, err := NewJSONSignatureFromMap(testMap)
+ if err != nil {
+ t.Fatalf("Error creating JSONSignature from map: %s", err)
+ }
+
+ err = js.SignWithChain(trustKey, chain)
+ if err != nil {
+ t.Fatalf("Error signing with chain: %s", err)
+ }
+
+ pool := x509.NewCertPool()
+ pool.AddCert(ca)
+ chains, err := js.VerifyChains(pool)
+ if err != nil {
+ t.Fatalf("Error verifying content: %s", err)
+ }
+ if len(chains) != 1 {
+ t.Fatalf("Unexpected chains length: %d", len(chains))
+ }
+ if len(chains[0]) != 7 {
+ t.Fatalf("Unexpected chain length: %d", len(chains[0]))
+ }
+}
+
+func TestInvalidChain(t *testing.T) {
+ caKey, err := GenerateECP256PrivateKey()
+ if err != nil {
+ t.Fatalf("Error generating key: %s", err)
+ }
+ ca, err := testutil.GenerateTrustCA(caKey.CryptoPublicKey(), caKey.CryptoPrivateKey())
+ if err != nil {
+ t.Fatalf("Error generating ca: %s", err)
+ }
+ trustKey, chain := generateTrustChain(t, caKey, ca)
+
+ testMap, _ := createTestJSON("verifySignatures", " ")
+ js, err := NewJSONSignatureFromMap(testMap)
+ if err != nil {
+ t.Fatalf("Error creating JSONSignature from map: %s", err)
+ }
+
+ err = js.SignWithChain(trustKey, chain[:5])
+ if err != nil {
+ t.Fatalf("Error signing with chain: %s", err)
+ }
+
+ pool := x509.NewCertPool()
+ pool.AddCert(ca)
+ chains, err := js.VerifyChains(pool)
+ if err == nil {
+ t.Fatalf("Expected error verifying with bad chain")
+ }
+ if len(chains) != 0 {
+ t.Fatalf("Unexpected chains returned from invalid verify")
+ }
+}
+
+func TestMergeSignatures(t *testing.T) {
+ pk1, err := GenerateECP256PrivateKey()
+ if err != nil {
+ t.Fatalf("unexpected error generating private key 1: %v", err)
+ }
+
+ pk2, err := GenerateECP256PrivateKey()
+ if err != nil {
+ t.Fatalf("unexpected error generating private key 2: %v", err)
+ }
+
+ payload := make([]byte, 1<<10)
+ if _, err = io.ReadFull(rand.Reader, payload); err != nil {
+ t.Fatalf("error generating payload: %v", err)
+ }
+
+ payload, _ = json.Marshal(map[string]interface{}{"data": payload})
+
+ sig1, err := NewJSONSignature(payload)
+ if err != nil {
+ t.Fatalf("unexpected error creating signature 1: %v", err)
+ }
+
+ if err := sig1.Sign(pk1); err != nil {
+ t.Fatalf("unexpected error signing with pk1: %v", err)
+ }
+
+ sig2, err := NewJSONSignature(payload)
+ if err != nil {
+ t.Fatalf("unexpected error creating signature 2: %v", err)
+ }
+
+ if err := sig2.Sign(pk2); err != nil {
+ t.Fatalf("unexpected error signing with pk2: %v", err)
+ }
+
+ // Now, we actually merge into sig1
+ if err := sig1.Merge(sig2); err != nil {
+ t.Fatalf("unexpected error merging: %v", err)
+ }
+
+ // Verify the new signature package
+ pubkeys, err := sig1.Verify()
+ if err != nil {
+ t.Fatalf("unexpected error during verify: %v", err)
+ }
+
+ // Make sure the pubkeys match the two private keys from before
+ privkeys := map[string]PrivateKey{
+ pk1.KeyID(): pk1,
+ pk2.KeyID(): pk2,
+ }
+
+ found := map[string]struct{}{}
+
+ for _, pubkey := range pubkeys {
+ if _, ok := privkeys[pubkey.KeyID()]; !ok {
+ t.Fatalf("unexpected public key found during verification: %v", pubkey)
+ }
+
+ found[pubkey.KeyID()] = struct{}{}
+ }
+
+ // Make sure we've found all the private keys from verification
+ for keyid, _ := range privkeys {
+ if _, ok := found[keyid]; !ok {
+ t.Fatalf("public key %v not found during verification", keyid)
+ }
+ }
+
+ // Create another signature, with a different payload, and ensure we get an error.
+ sig3, err := NewJSONSignature([]byte("{}"))
+ if err != nil {
+ t.Fatalf("unexpected error making signature for sig3: %v", err)
+ }
+
+ if err := sig1.Merge(sig3); err == nil {
+ t.Fatalf("error expected during invalid merge with different payload")
+ }
+}