diff --git a/lib/go/jsonsign/jsonsign_test.go b/lib/go/jsonsign/jsonsign_test.go index 2540cd15e..86e132576 100644 --- a/lib/go/jsonsign/jsonsign_test.go +++ b/lib/go/jsonsign/jsonsign_test.go @@ -20,7 +20,9 @@ import ( "camli/blobref" . "camli/testing" + "fmt" "os" + "strings" "sync" "testing" ) @@ -29,9 +31,89 @@ var unsigned = `{"camliVersion": 1, "camliType": "foo" }` +var pubKey1 = `-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.10 (GNU/Linux) + +mQENBEzgoVsBCAC/56aEJ9BNIGV9FVP+WzenTAkg12k86YqlwJVAB/VwdMlyXxvi +bCT1RVRfnYxscs14LLfcMWF3zMucw16mLlJCBSLvbZ0jn4h+/8vK5WuAdjw2YzLs +WtBcjWn3lV6tb4RJz5gtD/o1w8VWxwAnAVIWZntKAWmkcChCRgdUeWso76+plxE5 +aRYBJqdT1mctGqNEISd/WYPMgwnWXQsVi3x4z1dYu2tD9uO1dkAff12z1kyZQIBQ +rexKYRRRh9IKAayD4kgS0wdlULjBU98aeEaMz1ckuB46DX3lAYqmmTEL/Rl9cOI0 +Enpn/oOOfYFa5h0AFndZd1blMvruXfdAobjVABEBAAG0JUNhbWxpIFRlc3RlciA8 +Y2FtbGktdGVzdEBleGFtcGxlLmNvbT6JATgEEwECACIFAkzgoVsCGwMGCwkIBwMC +BhUIAgkKCwQWAgMBAh4BAheAAAoJECkxpnwm9avaHE0IAJ/pMZgiURl3kefrFMAV +7ei0XDfTekZOwDRcZWTVQ/A97phpzO8t78qLYbFeHuq3myNhrlVO9Gyp+2V904rN +dudoHLhpegf5TNeHGmAGHBxcooMPMp0JyIDnUBxtCNGxgWfbKpEDRsQAjkCc7sR0 +H+OegzlEf6JZGzEhV5ohOioTsC1DmJNoQsRz5Kes7sLoAzpQCbCv4yv+1o+mnzgW +9qPJXKxcScc0t2YTvcvpJ7LV8no1OP6vpYqB1A9Pzze6XFBlcXOUKbRKk0fEIV/u +pU3ph1fF7wlyRgA4A3iPwDC4BgVmHYkz9nYPn+7IcT/dDig5SWU+n7WZgGeyv75y +0Ue5AQ0ETOChWwEIALuHxKI+oSH+eeMSXhxcSUXnhp4cUeyvOV7oNPYcmsDclF0Y +7y8NrSPiEZod9vSTEDMq7hd3BG+feCBqjgR4qtmoXguJhWcnJqDBk5iAMuuAph9O +CC8QLACMJPhoxQ0UtDPKlpG4X8kLK1woHd716ulPl2KLjTgd6K4kCGj+CV5Ekn6u +IJj+3IPbYDOwk1l06ksimwQAY4dA1CXOTviH1bVqR6CzuzVPg4hcryWDva1rEO5c +LcOR8Wk/thANFLSNjqX8UgtGXhFZRWxKetFDQiX5f2BKoqTVYvD3pqt+zzyLNFAz +xhMc3cyFfqM8yQdzdEey/DIWtMoDqZCSVMJ63N8AEQEAAYkBHwQYAQIACQUCTOCh +WwIbDAAKCRApMaZ8JvWr2mHACACkco+fAfRK+gmprF2m8E0Bp1frwFH0g4RJVHXQ +BUDbg7OZbWumzD4Br28si6XDVMP6fLOeyD0EHYb6LhAHDkBLqx6e3kKG1mQ8fMIV +O4YMQfskYH2FJqlCtgMnM8N3oslPBTpZedNPSUq7HJh2pKr9GIDi1V+Hgc/qEigE +dj9f2zSSaKZdC4eL73GvlQOh+4XqgaMnMiKfI+/2WlRaJs1KOgKmIp5yHt0qY0ef +y+40BY/z9pMjyUvr/Wwp8KXArw0NAwzp8NUl5fNxRg9XWQWLn6hW8ydR20X3t2ym +iNSWzNQiTT6k7fumOABCoSZsow/AJxQSxqKOJBjgpKjIKCgY +=ru0J +-----END PGP PUBLIC KEY BLOCK-----` + +var pubKeyBlob1 = &blobref.TestBlob{pubKey1} + +var testFetcher = &TestFetcher{} + +func init() { + testFetcher.AddBlob(pubKeyBlob1) +} + +func TestSigningBadInput(t *testing.T) { + sr := newRequest() + + sr.UnsignedJson = "" + _, err := sr.Sign() + ExpectErrorContains(t, err, "json parse error", "empty input") + + sr.UnsignedJson = "{}" + _, err = sr.Sign() + ExpectErrorContains(t, err, "json lacks \"camliSigner\" key", "just braces") + + sr.UnsignedJson = `{"camliSigner": 123}` + _, err = sr.Sign() + ExpectErrorContains(t, err, "\"camliSigner\" key is malformed or unsupported", "camliSigner 123") + + sr.UnsignedJson = `{"camliSigner": ""}` + _, err = sr.Sign() + ExpectErrorContains(t, err, "\"camliSigner\" key is malformed or unsupported", "empty camliSigner") +} + +func newRequest() *SignRequest { + return &SignRequest{ + UnsignedJson: "", + Fetcher: testFetcher, + UseAgent: false, + ServerMode: true, + SecretKeyringPath: "./testdata/test-secring.gpg", + KeyringPath: "./testdata/test-keyring.gpg", + } +} + +func TestSigning(t *testing.T) { + sr := newRequest() + sr.UnsignedJson = fmt.Sprintf(`{"camliSigner": %q}`, pubKeyBlob1.BlobRef().String()) + got, err := sr.Sign() + AssertNil(t, err, "no error signing") + Expect(t, strings.Contains(got, `"camliSig":`), "got a camliSig") + + t.Logf("TODO: finish these tests; verify things round-trip, verify GPG external-vs-Go sign & verify round-trip, test signatures from wrong signer don't verify, etc.") +} + type TestFetcher struct { - l sync.Mutex - m map[string]*blobref.TestBlob + l sync.Mutex + m map[string]*blobref.TestBlob } func (tf *TestFetcher) AddBlob(b *blobref.TestBlob) { @@ -45,8 +127,8 @@ func (tf *TestFetcher) AddBlob(b *blobref.TestBlob) { func (tf *TestFetcher) Fetch(ref *blobref.BlobRef) (file blobref.ReadSeekCloser, size int64, err os.Error) { tf.l.Lock() - defer tf.l.Unlock() - if tf.m == nil { + defer tf.l.Unlock() + if tf.m == nil { err = os.ENOENT return } @@ -82,56 +164,14 @@ func (sr *strReader) Seek(offset int64, whence int) (ret int64, err os.Error) { } func (sr *strReader) Read(p []byte) (n int, err os.Error) { - remain := len(sr.s) - sr.pos - if remain <= 0 { + if sr.pos >= len(sr.s) { err = os.EOF return } - toCopy := len(p) - if remain < toCopy { - toCopy = remain + n = copy(p, sr.s[sr.pos:]) + if n == 0 { + err = os.EOF } - copy(p, sr.s[sr.pos:sr.pos+toCopy]) + sr.pos += n return } - -var testFetcher = &TestFetcher{} - -func TestSigningBadInput(t *testing.T) { - sr := newRequest() - - sr.UnsignedJson = "" - _, err := sr.Sign() - ExpectErrorContains(t, err, "json parse error", "empty input") - - sr.UnsignedJson = "{}" - _, err = sr.Sign() - ExpectErrorContains(t, err, "json lacks \"camliSigner\" key", "just braces") - - sr.UnsignedJson = `{"camliSigner": 123}` - _, err = sr.Sign() - ExpectErrorContains(t, err, "\"camliSigner\" key is malformed or unsupported", "camliSigner 123") - - sr.UnsignedJson = `{"camliSigner": ""}` - _, err = sr.Sign() - ExpectErrorContains(t, err, "\"camliSigner\" key is malformed or unsupported", "empty camliSigner") -} - -func newRequest() *SignRequest { - return &SignRequest{ - UnsignedJson: "", - Fetcher: testFetcher, - UseAgent: false, - ServerMode: true, - } -} - -func TestSigning(t *testing.T) { - sr := newRequest() - // TODO: finish test - got, err := sr.Sign() - if err != nil { - //t.Logf("Error signing: %v", err) - } - t.Logf("TODO; finish these tests; got: %s", got) -} diff --git a/lib/go/jsonsign/sign.go b/lib/go/jsonsign/sign.go index 0558a5e9a..81fa982c1 100644 --- a/lib/go/jsonsign/sign.go +++ b/lib/go/jsonsign/sign.go @@ -46,6 +46,23 @@ type SignRequest struct { // In server-mode, don't use any default (user) keys // TODO: formalize what this means? ServerMode bool + + SecretKeyringPath string + KeyringPath string +} + +func (sr *SignRequest) publicRingPath() string { + if sr.KeyringPath != "" { + return sr.KeyringPath + } + return *flagRing +} + +func (sr *SignRequest) secretRingPath() string { + if sr.SecretKeyringPath != "" { + return sr.SecretKeyringPath + } + return *flagSecretRing } func (sr *SignRequest) Sign() (signedJson string, err os.Error) { @@ -106,8 +123,8 @@ func (sr *SignRequest) Sign() (signedJson string, err os.Error) { if sr.ServerMode { args = append(args, "--no-default-keyring", - "--keyring", *flagRing, // TODO: needed for signing? - "--secret-keyring", *flagSecretRing) + "--keyring", sr.publicRingPath(), // TODO: needed for signing? + "--secret-keyring", sr.secretRingPath()) } args = append(args, "-") diff --git a/lib/go/jsonsign/testdata/test-keyring.gpg b/lib/go/jsonsign/testdata/test-keyring.gpg new file mode 100644 index 000000000..3d20ba683 Binary files /dev/null and b/lib/go/jsonsign/testdata/test-keyring.gpg differ diff --git a/lib/go/jsonsign/testdata/test-keyring2.gpg b/lib/go/jsonsign/testdata/test-keyring2.gpg new file mode 100644 index 000000000..ded7d5151 Binary files /dev/null and b/lib/go/jsonsign/testdata/test-keyring2.gpg differ diff --git a/lib/go/jsonsign/testdata/test-secring.gpg b/lib/go/jsonsign/testdata/test-secring.gpg new file mode 100644 index 000000000..bca3ad039 Binary files /dev/null and b/lib/go/jsonsign/testdata/test-secring.gpg differ diff --git a/lib/go/jsonsign/testdata/test-secring2.gpg b/lib/go/jsonsign/testdata/test-secring2.gpg new file mode 100644 index 000000000..f4b7ed222 Binary files /dev/null and b/lib/go/jsonsign/testdata/test-secring2.gpg differ