Skip to content

Commit c6184db

Browse files
authored
Add buildCp tests (#197)
* Add `buildCp` tests * Unexport `RFC6962NoteSignature`
1 parent 38fedd4 commit c6184db

File tree

2 files changed

+58
-5
lines changed

2 files changed

+58
-5
lines changed

internal/scti/signatures.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ func buildV1SCT(signer crypto.Signer, leaf *rfc6962.MerkleTreeLeaf) (*rfc6962.Si
106106
}
107107

108108
type rfc6962NoteSignature struct {
109-
timestamp uint64
110-
signature rfc6962.DigitallySigned
109+
Timestamp uint64
110+
Signature rfc6962.DigitallySigned
111111
}
112112

113113
// serializeSTHSignatureInput serializes the passed in STH into the correct
@@ -133,7 +133,6 @@ func serializeSTHSignatureInput(sth rfc6962.SignedTreeHead) ([]byte, error) {
133133
}
134134

135135
// buildCp builds a https://c2sp.org/static-ct-api checkpoint.
136-
// TODO(phboneff): add tests
137136
func buildCp(signer crypto.Signer, size uint64, timeMilli uint64, hash []byte) ([]byte, error) {
138137
sth := rfc6962.SignedTreeHead{
139138
Version: rfc6962.V1,
@@ -154,8 +153,8 @@ func buildCp(signer crypto.Signer, size uint64, timeMilli uint64, hash []byte) (
154153
}
155154

156155
rfc6962Note := rfc6962NoteSignature{
157-
timestamp: sth.Timestamp,
158-
signature: rfc6962.DigitallySigned{
156+
Timestamp: sth.Timestamp,
157+
Signature: rfc6962.DigitallySigned{
159158
Algorithm: tls.SignatureAndHashAlgorithm{
160159
Hash: tls.SHA256,
161160
Signature: tls.SignatureAlgorithmFromPubKey(signer.Public()),

internal/scti/signatures_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package scti
1717
import (
1818
"bytes"
1919
"crypto"
20+
"crypto/ecdsa"
2021
"crypto/sha256"
2122
"crypto/x509"
2223
"encoding/hex"
@@ -401,3 +402,56 @@ func setupSigner(fakeSig []byte) (crypto.Signer, error) {
401402

402403
return testdata.NewSignerWithFixedSig(key, fakeSig), nil
403404
}
405+
406+
func TestBuildCp(t *testing.T) {
407+
// Create a test signer.
408+
ecdsaSigner, err := loadPEMPrivateKey("../testdata/test_ct_server_ecdsa_private_key.pem")
409+
if err != nil {
410+
t.Fatalf("Can't open key: %v", err)
411+
}
412+
413+
// Define test data.
414+
size := uint64(12345)
415+
hash := []byte("test_hash_value_12345678901234567890")
416+
417+
// Build the checkpoint which is in the RFC6962NoteSignature format.
418+
checkpoint, err := buildCp(ecdsaSigner, size, fixedTimeMillis, hash)
419+
if err != nil {
420+
t.Errorf("buildCp failed: %v", err)
421+
}
422+
423+
// Verify whether the checkpoint is empty.
424+
if len(checkpoint) == 0 {
425+
t.Errorf("buildCp returned an empty checkpoint")
426+
}
427+
428+
// Verify that the checkpoint can be parsed.
429+
var sig rfc6962NoteSignature
430+
_, err = tls.Unmarshal(checkpoint, &sig)
431+
if err != nil {
432+
t.Errorf("failed to unmarshal checkpoint: %v", err)
433+
}
434+
// Verify the timestamp in the note signature.
435+
if sig.Timestamp != fixedTimeMillis {
436+
t.Errorf("buildCp returned wrong timestamp, got %d, want %d", sig.Timestamp, fixedTimeMillis)
437+
}
438+
439+
// Verify the signature using the public key.
440+
sth := rfc6962.SignedTreeHead{
441+
Version: rfc6962.V1,
442+
TreeSize: size,
443+
Timestamp: fixedTimeMillis,
444+
}
445+
copy(sth.SHA256RootHash[:], hash)
446+
447+
sthBytes, err := serializeSTHSignatureInput(sth)
448+
if err != nil {
449+
t.Fatalf("serializeSTHSignatureInput(): %v", err)
450+
}
451+
452+
h := sha256.Sum256(sthBytes)
453+
valid := ecdsa.VerifyASN1(ecdsaSigner.Public().(*ecdsa.PublicKey), h[:], sig.Signature.Signature)
454+
if !valid {
455+
t.Errorf("buildCp returned an invalid signature")
456+
}
457+
}

0 commit comments

Comments
 (0)