...

Source file src/github.com/google/certificate-transparency-go/trillian/ctfe/serialize_test.go

Documentation: github.com/google/certificate-transparency-go/trillian/ctfe

     1  // Copyright 2016 Google LLC. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package ctfe
    16  
    17  import (
    18  	"bytes"
    19  	"crypto/sha256"
    20  	"testing"
    21  
    22  	"github.com/google/certificate-transparency-go/tls"
    23  	"github.com/google/certificate-transparency-go/trillian/ctfe/testonly"
    24  	"github.com/google/certificate-transparency-go/trillian/testdata"
    25  	"github.com/google/certificate-transparency-go/x509"
    26  	"github.com/google/certificate-transparency-go/x509util"
    27  	"github.com/google/trillian/crypto/keys/pem"
    28  	"github.com/kylelemons/godebug/pretty"
    29  
    30  	ct "github.com/google/certificate-transparency-go"
    31  )
    32  
    33  func TestBuildV1MerkleTreeLeafForCert(t *testing.T) {
    34  	cert, err := x509util.CertificateFromPEM([]byte(testonly.LeafSignedByFakeIntermediateCertPEM))
    35  	if x509.IsFatal(err) {
    36  		t.Fatalf("failed to set up test cert: %v", err)
    37  	}
    38  
    39  	signer, err := setupSigner(fakeSignature)
    40  	if err != nil {
    41  		t.Fatalf("could not create signer: %v", err)
    42  	}
    43  
    44  	leaf, err := ct.MerkleTreeLeafFromChain([]*x509.Certificate{cert}, ct.X509LogEntryType, fixedTimeMillis)
    45  	if err != nil {
    46  		t.Fatalf("buildV1MerkleTreeLeafForCert()=nil,%v; want _,nil", err)
    47  	}
    48  	got, err := buildV1SCT(signer, leaf)
    49  	if err != nil {
    50  		t.Fatalf("buildV1SCT()=nil,%v; want _,nil", err)
    51  	}
    52  
    53  	expected := ct.SignedCertificateTimestamp{
    54  		SCTVersion: 0,
    55  		LogID:      ct.LogID{KeyID: demoLogID},
    56  		Timestamp:  fixedTimeMillis,
    57  		Extensions: ct.CTExtensions{},
    58  		Signature: ct.DigitallySigned{
    59  			Algorithm: tls.SignatureAndHashAlgorithm{
    60  				Hash:      tls.SHA256,
    61  				Signature: tls.ECDSA},
    62  			Signature: fakeSignature,
    63  		},
    64  	}
    65  
    66  	if diff := pretty.Compare(*got, expected); diff != "" {
    67  		t.Fatalf("Mismatched SCT (cert), diff:\n%v", diff)
    68  	}
    69  
    70  	// Additional checks that the MerkleTreeLeaf we built is correct
    71  	if got, want := leaf.Version, ct.V1; got != want {
    72  		t.Fatalf("Got a %v leaf, expected a %v leaf", got, want)
    73  	}
    74  	if got, want := leaf.LeafType, ct.TimestampedEntryLeafType; got != want {
    75  		t.Fatalf("Got leaf type %v, expected %v", got, want)
    76  	}
    77  	if got, want := leaf.TimestampedEntry.EntryType, ct.X509LogEntryType; got != want {
    78  		t.Fatalf("Got entry type %v, expected %v", got, want)
    79  	}
    80  	if got, want := leaf.TimestampedEntry.Timestamp, got.Timestamp; got != want {
    81  		t.Fatalf("Entry / sct timestamp mismatch; got %v, expected %v", got, want)
    82  	}
    83  	if got, want := leaf.TimestampedEntry.X509Entry.Data, cert.Raw; !bytes.Equal(got, want) {
    84  		t.Fatalf("Cert bytes mismatch, got %x, expected %x", got, want)
    85  	}
    86  }
    87  
    88  func TestSignV1SCTForPrecertificate(t *testing.T) {
    89  	cert, err := x509util.CertificateFromPEM([]byte(testonly.PrecertPEMValid))
    90  	if x509.IsFatal(err) {
    91  		t.Fatalf("failed to set up test precert: %v", err)
    92  	}
    93  
    94  	signer, err := setupSigner(fakeSignature)
    95  	if err != nil {
    96  		t.Fatalf("could not create signer: %v", err)
    97  	}
    98  
    99  	// Use the same cert as the issuer for convenience.
   100  	leaf, err := ct.MerkleTreeLeafFromChain([]*x509.Certificate{cert, cert}, ct.PrecertLogEntryType, fixedTimeMillis)
   101  	if err != nil {
   102  		t.Fatalf("buildV1MerkleTreeLeafForCert()=nil,%v; want _,nil", err)
   103  	}
   104  	got, err := buildV1SCT(signer, leaf)
   105  	if err != nil {
   106  		t.Fatalf("buildV1SCT()=nil,%v; want _,nil", err)
   107  	}
   108  
   109  	expected := ct.SignedCertificateTimestamp{
   110  		SCTVersion: 0,
   111  		LogID:      ct.LogID{KeyID: demoLogID},
   112  		Timestamp:  fixedTimeMillis,
   113  		Extensions: ct.CTExtensions{},
   114  		Signature: ct.DigitallySigned{
   115  			Algorithm: tls.SignatureAndHashAlgorithm{
   116  				Hash:      tls.SHA256,
   117  				Signature: tls.ECDSA},
   118  			Signature: fakeSignature}}
   119  
   120  	if diff := pretty.Compare(*got, expected); diff != "" {
   121  		t.Fatalf("Mismatched SCT (precert), diff:\n%v", diff)
   122  	}
   123  
   124  	// Additional checks that the MerkleTreeLeaf we built is correct
   125  	if got, want := leaf.Version, ct.V1; got != want {
   126  		t.Fatalf("Got a %v leaf, expected a %v leaf", got, want)
   127  	}
   128  	if got, want := leaf.LeafType, ct.TimestampedEntryLeafType; got != want {
   129  		t.Fatalf("Got leaf type %v, expected %v", got, want)
   130  	}
   131  	if got, want := leaf.TimestampedEntry.EntryType, ct.PrecertLogEntryType; got != want {
   132  		t.Fatalf("Got entry type %v, expected %v", got, want)
   133  	}
   134  	if got, want := got.Timestamp, leaf.TimestampedEntry.Timestamp; got != want {
   135  		t.Fatalf("Entry / sct timestamp mismatch; got %v, expected %v", got, want)
   136  	}
   137  	keyHash := sha256.Sum256(cert.RawSubjectPublicKeyInfo)
   138  	if got, want := keyHash[:], leaf.TimestampedEntry.PrecertEntry.IssuerKeyHash[:]; !bytes.Equal(got, want) {
   139  		t.Fatalf("Issuer key hash bytes mismatch, got %v, expected %v", got, want)
   140  	}
   141  	defangedTBS, _ := x509.RemoveCTPoison(cert.RawTBSCertificate)
   142  	if got, want := leaf.TimestampedEntry.PrecertEntry.TBSCertificate, defangedTBS; !bytes.Equal(got, want) {
   143  		t.Fatalf("TBS cert mismatch, got %v, expected %v", got, want)
   144  	}
   145  }
   146  
   147  func TestSignV1TreeHead(t *testing.T) {
   148  	signer, err := pem.UnmarshalPrivateKey(testdata.DemoPrivateKey, testdata.DemoPrivateKeyPass)
   149  	if err != nil {
   150  		t.Fatalf("could not create signer: %v", err)
   151  	}
   152  	var cache SignatureCache
   153  
   154  	sth := ct.SignedTreeHead{
   155  		Version:   ct.V1,
   156  		TreeSize:  10,
   157  		Timestamp: 1512993312000,
   158  	}
   159  	if err := signV1TreeHead(signer, &sth, &cache); err != nil {
   160  		t.Fatalf("signV1TreeHead()=%v; want nil", err)
   161  	}
   162  	prevSig := make([]byte, len(sth.TreeHeadSignature.Signature))
   163  	copy(prevSig, sth.TreeHeadSignature.Signature)
   164  
   165  	// Signing the same contents should get the same cached signature regardless.
   166  	for i := 0; i < 5; i++ {
   167  		if err := signV1TreeHead(signer, &sth, &cache); err != nil {
   168  			t.Fatalf("signV1TreeHead()=%v; want nil", err)
   169  		}
   170  		sig := make([]byte, len(sth.TreeHeadSignature.Signature))
   171  		copy(sig, sth.TreeHeadSignature.Signature)
   172  
   173  		if diff := pretty.Compare(prevSig, sig); diff != "" {
   174  			t.Fatalf("signV1TreeHead().TreeHeadSignature mismatched, diff:\n%v", diff)
   175  		}
   176  	}
   177  
   178  	// But changing the contents does change the signature.
   179  	for i := 0; i < 5; i++ {
   180  		sth.TreeSize = uint64(11 + i)
   181  		if err := signV1TreeHead(signer, &sth, &cache); err != nil {
   182  			t.Errorf("signV1TreeHead()=%v; want nil", err)
   183  		}
   184  		sig := make([]byte, len(sth.TreeHeadSignature.Signature))
   185  		copy(sig, sth.TreeHeadSignature.Signature)
   186  
   187  		if bytes.Equal(prevSig, sig) {
   188  			t.Fatalf("signV1TreeHead(size=%d).TreeHeadSignature unexpectedly matched", sth.TreeSize)
   189  		}
   190  		prevSig := sig
   191  
   192  		// Repeating should again return the cached signature.
   193  		if err := signV1TreeHead(signer, &sth, &cache); err != nil {
   194  			t.Errorf("signV1TreeHead(size=%d)=%v; want nil", sth.TreeSize, err)
   195  		}
   196  		sig = make([]byte, len(sth.TreeHeadSignature.Signature))
   197  		copy(sig, sth.TreeHeadSignature.Signature)
   198  		if diff := pretty.Compare(prevSig, sig); diff != "" {
   199  			t.Fatalf("signV1TreeHead(size=%d).TreeHeadSignature mismatched, diff:\n%v", sth.TreeSize, diff)
   200  		}
   201  	}
   202  }
   203  
   204  func TestSignV1TreeHeadDifferentSigners(t *testing.T) {
   205  	signer1, err := pem.UnmarshalPrivateKey(testdata.DemoPrivateKey, testdata.DemoPrivateKeyPass)
   206  	if err != nil {
   207  		t.Fatalf("could not create signer1: %v", err)
   208  	}
   209  	signer2, err := setupSigner(fakeSignature)
   210  	if err != nil {
   211  		t.Fatalf("could not create signer2: %v", err)
   212  	}
   213  
   214  	var cache1, cache2 SignatureCache
   215  	sth := ct.SignedTreeHead{
   216  		Version:   ct.V1,
   217  		TreeSize:  10,
   218  		Timestamp: 1512993312000,
   219  	}
   220  
   221  	if err := signV1TreeHead(signer1, &sth, &cache1); err != nil {
   222  		t.Fatalf("signV1TreeHead(signer1)=%v; want nil", err)
   223  	}
   224  	sig1 := make([]byte, len(sth.TreeHeadSignature.Signature))
   225  	copy(sig1, sth.TreeHeadSignature.Signature)
   226  
   227  	if err := signV1TreeHead(signer2, &sth, &cache2); err != nil {
   228  		t.Fatalf("signV1TreeHead(signer2)=%v; want nil", err)
   229  	}
   230  	sig2 := make([]byte, len(sth.TreeHeadSignature.Signature))
   231  	copy(sig2, sth.TreeHeadSignature.Signature)
   232  
   233  	// Check that different signers on the same contents give different results.
   234  	if bytes.Equal(sig1, sig2) {
   235  		t.Fatal("signV1TreeHead().TreeHeadSignature unexpectedly matched")
   236  	}
   237  }
   238  

View as plain text