Skip to content

Commit 0bda0a9

Browse files
Fix CT integration server by giving it a key and making it sign things
1 parent 8e938de commit 0bda0a9

File tree

3 files changed

+96
-9
lines changed

3 files changed

+96
-9
lines changed

test/boulder-config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@
293293
"logs": [
294294
{
295295
"uri": "http://127.0.0.1:4500",
296-
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEfahLEimAoz2t01p3uMziiLOl/fHTDM0YDOhBRuiBARsV4UvxG2LdNgoIGLrtCzWE0J5APC2em4JlvR8EEEFMoA=="
296+
"key": "MHQCAQEEIGKI6QpOXNTBGdVaZ0938b0DEelF50qUDiWXvuB5oezjoAcGBSuBBAAKoUQDQgAEG7RPTHSjHhVDpR6XSishp/soJqHJHDvGpyc6TGJdHx+aD0wpi9knCJFpaxPTNDg0wWc3PtzLmlhlzeXu4lhDpQ=="
297297
}
298298
],
299299
"intermediateBundleFilename": "test/test-ca.pem"

test/ct-key.pem

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-----BEGIN EC PRIVATE KEY-----
2+
MHQCAQEEIGKI6QpOXNTBGdVaZ0938b0DEelF50qUDiWXvuB5oezjoAcGBSuBBAAK
3+
oUQDQgAEG7RPTHSjHhVDpR6XSishp/soJqHJHDvGpyc6TGJdHx+aD0wpi9knCJFp
4+
axPTNDg0wWc3PtzLmlhlzeXu4lhDpQ==
5+
-----END EC PRIVATE KEY-----

test/ct-test-srv/main.go

Lines changed: 90 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,78 @@
99
package main
1010

1111
import (
12+
"crypto/ecdsa"
13+
"crypto/rand"
14+
"crypto/sha256"
15+
"crypto/x509"
16+
"encoding/asn1"
17+
"encoding/base64"
1218
"encoding/json"
19+
"flag"
1320
"fmt"
1421
"io/ioutil"
1522
"log"
23+
"math/big"
1624
"net/http"
25+
"os"
1726
"sync/atomic"
27+
28+
ct "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/google/certificate-transparency/go"
1829
)
1930

31+
func createSignedSCT(leaf []byte, k *ecdsa.PrivateKey) []byte {
32+
rawKey, _ := x509.MarshalPKIXPublicKey(&k.PublicKey)
33+
pkHash := sha256.Sum256(rawKey)
34+
sct := ct.SignedCertificateTimestamp{
35+
SCTVersion: ct.V1,
36+
LogID: pkHash,
37+
Timestamp: 1337,
38+
}
39+
serialized, _ := ct.SerializeSCTSignatureInput(sct, ct.LogEntry{
40+
Leaf: ct.MerkleTreeLeaf{
41+
LeafType: ct.TimestampedEntryLeafType,
42+
TimestampedEntry: ct.TimestampedEntry{
43+
X509Entry: ct.ASN1Cert(leaf),
44+
EntryType: ct.X509LogEntryType,
45+
},
46+
},
47+
})
48+
hashed := sha256.Sum256(serialized)
49+
var ecdsaSig struct {
50+
R, S *big.Int
51+
}
52+
ecdsaSig.R, ecdsaSig.S, _ = ecdsa.Sign(rand.Reader, k, hashed[:])
53+
sig, _ := asn1.Marshal(ecdsaSig)
54+
55+
ds := ct.DigitallySigned{
56+
HashAlgorithm: ct.SHA256,
57+
SignatureAlgorithm: ct.ECDSA,
58+
Signature: sig,
59+
}
60+
61+
var jsonSCTObj struct {
62+
SCTVersion ct.Version `json:"sct_version"`
63+
ID string `json:"id"`
64+
Timestamp uint64 `json:"timestamp"`
65+
Extensions string `json:"extensions"`
66+
Signature string `json:"signature"`
67+
}
68+
jsonSCTObj.SCTVersion = ct.V1
69+
jsonSCTObj.ID = base64.StdEncoding.EncodeToString(pkHash[:])
70+
jsonSCTObj.Timestamp = 1337
71+
jsonSCTObj.Signature, _ = ds.Base64String()
72+
73+
jsonSCT, _ := json.Marshal(jsonSCTObj)
74+
return jsonSCT
75+
}
76+
2077
type ctSubmissionRequest struct {
2178
Chain []string `json:"chain"`
2279
}
2380

2481
type integrationSrv struct {
2582
submissions int64
83+
key *ecdsa.PrivateKey
2684
}
2785

2886
func (is *integrationSrv) handler(w http.ResponseWriter, r *http.Request) {
@@ -42,17 +100,21 @@ func (is *integrationSrv) handler(w http.ResponseWriter, r *http.Request) {
42100
if err != nil {
43101
http.Error(w, err.Error(), http.StatusBadRequest)
44102
}
103+
if len(addChainReq.Chain) == 0 {
104+
w.WriteHeader(400)
105+
return
106+
}
107+
108+
leaf, err := base64.StdEncoding.DecodeString(addChainReq.Chain[0])
109+
if err != nil {
110+
w.WriteHeader(400)
111+
return
112+
}
45113

46114
w.WriteHeader(http.StatusOK)
47115
// id is a sha256 of a random EC key. Generate your own with:
48116
// openssl ecparam -name prime256v1 -genkey -outform der | openssl sha256 -binary | base64
49-
w.Write([]byte(`{
50-
"sct_version": 0,
51-
"id": "8fjM8cvLPOhzCFwI62IYJhjkOcvWFLx1dMJbs0uhxJU=",
52-
"timestamp": 1442400000,
53-
"extensions": "",
54-
"signature": "BAMARzBFAiBB5wKED8KqKhADT37n0y28fZIPiGbCfZRVKq0wNo0hrwIhAOIa2tPBF/rB1y30Y/ROh4LBmJ0mItAbTWy8XZKh7Wcp"
55-
}`))
117+
w.Write(createSignedSCT(leaf, is.key))
56118
atomic.AddInt64(&is.submissions, 1)
57119
case "/submissions":
58120
if r.Method != "GET" {
@@ -70,7 +132,27 @@ func (is *integrationSrv) handler(w http.ResponseWriter, r *http.Request) {
70132
}
71133

72134
func main() {
73-
is := integrationSrv{}
135+
signingKey := flag.String("signingKey", "test/ct-key.pem", "Key to use for signing SCT receipts")
136+
flag.Parse()
137+
138+
if *signingKey == "" {
139+
fmt.Fprintf(os.Stderr, "--signingKey is required\n")
140+
os.Exit(1)
141+
}
142+
143+
keyBytes, err := ioutil.ReadFile(*signingKey)
144+
if err != nil {
145+
fmt.Fprintf(os.Stderr, "failed to read signing key file\n")
146+
return
147+
}
148+
149+
key, err := x509.ParseECPrivateKey(keyBytes)
150+
if err != nil {
151+
fmt.Fprintf(os.Stderr, "failed to parse signing key file\n")
152+
return
153+
}
154+
155+
is := integrationSrv{key: key}
74156
s := &http.Server{
75157
Addr: "localhost:4500",
76158
Handler: http.HandlerFunc(is.handler),

0 commit comments

Comments
 (0)