2010-11-30 07:22:11 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
2010-12-03 15:34:24 +00:00
|
|
|
$ gpg --no-default-keyring --keyring=/tmp/foo --import --armor test/pubkey-blobs/sha1-82e6f3494f69
|
2010-11-30 07:22:11 +00:00
|
|
|
|
2010-12-03 15:34:24 +00:00
|
|
|
$ gpg --no-default-keyring --keyring=/tmp/foo --verify sig.tmp doc.tmp ; echo $?
|
|
|
|
gpg: Signature made Mon 29 Nov 2010 10:59:52 PM PST using RSA key ID 26F5ABDA
|
|
|
|
gpg: Good signature from "Camli Tester <camli-test@example.com>"
|
|
|
|
gpg: WARNING: This key is not certified with a trusted signature!
|
|
|
|
gpg: There is no indication that the signature belongs to the owner.
|
|
|
|
Primary key fingerprint: FBB8 9AA3 20A2 806F E497 C049 2931 A67C 26F5 ABDA0
|
2010-11-30 07:22:11 +00:00
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
import (
|
2010-12-04 02:56:33 +00:00
|
|
|
"bytes"
|
2010-12-03 15:34:24 +00:00
|
|
|
// "crypto/openpgp/armor"
|
|
|
|
// "crypto/openpgp/packet"
|
|
|
|
/// "crypto/rsa"
|
|
|
|
// "crypto/sha1"
|
|
|
|
// "io/ioutil"
|
|
|
|
"camli/blobref"
|
|
|
|
"json"
|
|
|
|
"log"
|
|
|
|
"flag"
|
2010-11-30 07:22:11 +00:00
|
|
|
"camli/http_util"
|
|
|
|
"http"
|
2010-12-03 15:34:24 +00:00
|
|
|
)
|
|
|
|
|
2010-12-04 02:56:33 +00:00
|
|
|
const sigSeparator = `,"camliSig":"`
|
|
|
|
|
2010-12-03 15:34:24 +00:00
|
|
|
var flagPubKeyDir *string = flag.String("pubkey-dir", "test/pubkey-blobs",
|
|
|
|
"Temporary development hack; directory to dig-xxxx.camli public keys.")
|
2010-11-30 07:22:11 +00:00
|
|
|
|
|
|
|
func handleVerify(conn http.ResponseWriter, req *http.Request) {
|
|
|
|
if !(req.Method == "POST" && req.URL.Path == "/camli/sig/verify") {
|
|
|
|
http_util.BadRequestError(conn, "Inconfigured handler.")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2010-12-03 15:34:24 +00:00
|
|
|
verifyFail := func(msg string) {
|
|
|
|
conn.WriteHeader(http.StatusOK) // no HTTP response code fun, error's in JSON
|
|
|
|
m := make(map[string]interface{})
|
|
|
|
m["signatureValid"] = 0
|
|
|
|
m["errorMessage"] = msg
|
|
|
|
http_util.ReturnJson(conn, m)
|
|
|
|
}
|
|
|
|
|
2010-11-30 07:22:11 +00:00
|
|
|
req.ParseForm()
|
|
|
|
|
2010-12-03 15:34:24 +00:00
|
|
|
sjson := req.FormValue("sjson")
|
|
|
|
if sjson == "" {
|
2010-11-30 07:22:11 +00:00
|
|
|
http_util.BadRequestError(conn, "Missing sjson parameter.")
|
|
|
|
return
|
|
|
|
}
|
2010-12-04 02:56:33 +00:00
|
|
|
|
|
|
|
// See doc/json-signing/* for background and details
|
|
|
|
// on these variable names.
|
|
|
|
|
|
|
|
BA := []byte(sjson)
|
|
|
|
sigIndex := bytes.LastIndex(BA, []byte(sigSeparator))
|
|
|
|
if sigIndex == -1 {
|
|
|
|
verifyFail("no 13-byte camliSig separator found in sjson")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// "Bytes Payload"
|
|
|
|
BP := BA[0:sigIndex]
|
|
|
|
|
|
|
|
// "Bytes Payload JSON". Note we re-use the memory (the ",")
|
|
|
|
// from BA in BPJ, so we can't re-use that "," byte for
|
|
|
|
// the opening "{" in "BS".
|
|
|
|
BPJ := BA[0:sigIndex+1]
|
|
|
|
BPJ[sigIndex] = '}'
|
|
|
|
|
|
|
|
BS := []byte("{" + sjson[sigIndex+1:])
|
|
|
|
|
|
|
|
log.Printf("BP = [%s]", string(BP))
|
|
|
|
log.Printf("BPJ = [%s]", string(BPJ))
|
|
|
|
log.Printf("BS = [%s]", string(BS))
|
2010-12-03 15:34:24 +00:00
|
|
|
|
|
|
|
sjsonKeys := make(map[string]interface{})
|
2010-12-04 02:56:33 +00:00
|
|
|
if err := json.Unmarshal(BPJ, &sjsonKeys); err != nil {
|
2010-12-03 15:34:24 +00:00
|
|
|
verifyFail("parse error; JSON is invalid")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, hasVersion := sjsonKeys["camliVersion"]; !hasVersion {
|
|
|
|
verifyFail("Missing 'camliVersion' in the JSON payload")
|
|
|
|
return
|
|
|
|
}
|
2010-11-30 07:22:11 +00:00
|
|
|
|
2010-12-03 15:34:24 +00:00
|
|
|
signer, hasSigner := sjsonKeys["camliSigner"]
|
|
|
|
if !hasSigner {
|
|
|
|
verifyFail("Missing 'camliSigner' in the JSON payload")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, ok := signer.(string); !ok {
|
|
|
|
verifyFail("Invalid 'camliSigner' in the JSON payload")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
signerBlob := blobref.Parse(signer.(string))
|
|
|
|
if signerBlob == nil {
|
|
|
|
verifyFail("Malformed 'camliSigner' blobref in the JSON payload")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
log.Printf("Signer: %v", signerBlob)
|
|
|
|
|
2010-12-04 02:56:33 +00:00
|
|
|
sigKey := make(map[string]interface{})
|
|
|
|
if err := json.Unmarshal(BPJ, &sigKey); err != nil {
|
|
|
|
verifyFail("parse error; signature JSON invalid")
|
|
|
|
}
|
|
|
|
|
2010-12-03 15:34:24 +00:00
|
|
|
log.Printf("Got json: %v", sjsonKeys)
|
2010-11-30 07:22:11 +00:00
|
|
|
conn.WriteHeader(http.StatusNotImplemented)
|
|
|
|
conn.Write([]byte("TODO: implement"))
|
|
|
|
}
|