99package main
1010
1111import (
12+ "crypto/ecdsa"
13+ "crypto/rand"
14+ "crypto/sha256"
15+ "crypto/x509"
16+ "encoding/asn1"
17+ "encoding/base64"
1218 "encoding/json"
1319 "fmt"
1420 "io/ioutil"
1521 "log"
22+ "math/big"
1623 "net/http"
24+ "os"
1725 "sync/atomic"
26+
27+ ct "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/google/certificate-transparency/go"
1828)
1929
30+ func createSignedSCT (leaf []byte , k * ecdsa.PrivateKey ) []byte {
31+ rawKey , _ := x509 .MarshalPKIXPublicKey (& k .PublicKey )
32+ pkHash := sha256 .Sum256 (rawKey )
33+ sct := ct.SignedCertificateTimestamp {
34+ SCTVersion : ct .V1 ,
35+ LogID : pkHash ,
36+ Timestamp : 1337 ,
37+ }
38+ serialized , _ := ct .SerializeSCTSignatureInput (sct , ct.LogEntry {
39+ Leaf : ct.MerkleTreeLeaf {
40+ LeafType : ct .TimestampedEntryLeafType ,
41+ TimestampedEntry : ct.TimestampedEntry {
42+ X509Entry : ct .ASN1Cert (leaf ),
43+ EntryType : ct .X509LogEntryType ,
44+ },
45+ },
46+ })
47+ hashed := sha256 .Sum256 (serialized )
48+ var ecdsaSig struct {
49+ R , S * big.Int
50+ }
51+ ecdsaSig .R , ecdsaSig .S , _ = ecdsa .Sign (rand .Reader , k , hashed [:])
52+ sig , _ := asn1 .Marshal (ecdsaSig )
53+
54+ ds := ct.DigitallySigned {
55+ HashAlgorithm : ct .SHA256 ,
56+ SignatureAlgorithm : ct .ECDSA ,
57+ Signature : sig ,
58+ }
59+
60+ var jsonSCTObj struct {
61+ SCTVersion ct.Version `json:"sct_version"`
62+ ID string `json:"id"`
63+ Timestamp uint64 `json:"timestamp"`
64+ Extensions string `json:"extensions"`
65+ Signature string `json:"signature"`
66+ }
67+ jsonSCTObj .SCTVersion = ct .V1
68+ jsonSCTObj .ID = base64 .StdEncoding .EncodeToString (pkHash [:])
69+ jsonSCTObj .Timestamp = 1337
70+ jsonSCTObj .Signature , _ = ds .Base64String ()
71+
72+ jsonSCT , _ := json .Marshal (jsonSCTObj )
73+ return jsonSCT
74+ }
75+
2076type ctSubmissionRequest struct {
2177 Chain []string `json:"chain"`
2278}
2379
2480type integrationSrv struct {
2581 submissions int64
82+ key * ecdsa.PrivateKey
2683}
2784
2885func (is * integrationSrv ) handler (w http.ResponseWriter , r * http.Request ) {
@@ -47,14 +104,16 @@ func (is *integrationSrv) handler(w http.ResponseWriter, r *http.Request) {
47104 return
48105 }
49106
107+ leaf , err := base64 .StdEncoding .DecodeString (addChainReq .Chain [0 ])
108+ if err != nil {
109+ w .WriteHeader (400 )
110+ return
111+ }
112+
50113 w .WriteHeader (http .StatusOK )
51- w .Write ([]byte (`{
52- "sct_version":0,
53- "id":"KHYaGJAn++880NYaAY12sFBXKcenQRvMvfYE9F1CYVM=",
54- "timestamp":1337,
55- "extensions":"",
56- "signature":"BAMARjBEAiAka/W0eYq23Iaih2wB2CGrAqlo92KyQuuY6WWumi1eNwIgBirYV/wsJvmZfGP5NrNYoWGIx1VV6NaNBIaSXh9hiYA="
57- }` ))
114+ // id is a sha256 of a random EC key. Generate your own with:
115+ // openssl ecparam -name prime256v1 -genkey -outform der | openssl sha256 -binary | base64
116+ w .Write (createSignedSCT (leaf , is .key ))
58117 atomic .AddInt64 (& is .submissions , 1 )
59118 case "/submissions" :
60119 if r .Method != "GET" {
@@ -72,7 +131,16 @@ func (is *integrationSrv) handler(w http.ResponseWriter, r *http.Request) {
72131}
73132
74133func main () {
75- is := integrationSrv {}
134+ signingKey := "MHcCAQEEIOCtGlGt/WT7471dOHdfBg43uJWJoZDkZAQjWfTitcVNoAoGCCqGSM49AwEHoUQDQgAEYggOxPnPkzKBIhTacSYoIfnSL2jPugcbUKx83vFMvk5gKAz/AGe87w20riuPwEGn229hKVbEKHFB61NIqNHC3Q=="
135+ decodedKey , _ := base64 .StdEncoding .DecodeString (signingKey )
136+
137+ key , err := x509 .ParseECPrivateKey (decodedKey )
138+ if err != nil {
139+ fmt .Fprintf (os .Stderr , "failed to parse signing key: %s\n " , err )
140+ return
141+ }
142+
143+ is := integrationSrv {key : key }
76144 s := & http.Server {
77145 Addr : "localhost:4500" ,
78146 Handler : http .HandlerFunc (is .handler ),
0 commit comments