Пример #1
0
func (fe *FileEntityFetcher) FetchEntity(keyId string) (*openpgp.Entity, error) {
	f, err := wkfs.Open(fe.File)
	if err != nil {
		return nil, fmt.Errorf("jsonsign: FetchEntity: %v", err)
	}
	defer f.Close()
	el, err := openpgp.ReadKeyRing(f)
	if err != nil {
		return nil, fmt.Errorf("jsonsign: openpgp.ReadKeyRing of %q: %v", fe.File, err)
	}
	for _, e := range el {
		pubk := &e.PrivateKey.PublicKey
		if pubk.KeyIdString() != keyId {
			continue
		}
		if e.PrivateKey.Encrypted {
			if err := fe.decryptEntity(e); err == nil {
				return e, nil
			} else {
				return nil, err
			}
		}
		return e, nil
	}
	return nil, fmt.Errorf("jsonsign: entity for keyid %q not found in %q", keyId, fe.File)
}
Пример #2
0
func serveHTTP(w http.ResponseWriter, r *http.Request) {
	rc, err := wkfs.Open(path.Join("/gcs", gcsBucket, r.URL.Path))
	if err != nil {
		http.Error(w, fmt.Sprintf("could not open %v: %v", r.URL.Path, err), 500)
		return
	}
	defer rc.Close()
	http.ServeContent(w, r, r.URL.Path, time.Now(), rc)
}
Пример #3
0
func TestWriteRead(t *testing.T) {
	if !metadata.OnGCE() {
		t.Skipf("Not testing on GCE")
	}
	if *flagBucket == "" {
		t.Skipf("No bucket specified")
	}
	ctx := context.Background()
	cl, err := storage.NewClient(ctx)
	it := cl.Bucket(*flagBucket).Objects(ctx, nil)
	if _, err := it.Next(); err != iterator.Done {
		if err == nil {
			t.Fatalf("Bucket %v is not empty, aborting test.", *flagBucket)
		}
		t.Fatalf("unexpected bucket iteration error: %v", err)
	}
	filename := "camli-gcs_test.txt"
	defer func() {
		if err := cl.Bucket(*flagBucket).Object(filename).Delete(ctx); err != nil {
			t.Fatalf("error while cleaning up: %v", err)
		}
	}()

	// Write to camli-gcs_test.txt
	gcsPath := "/gcs/" + *flagBucket + "/" + filename
	f, err := wkfs.Create(gcsPath)
	if err != nil {
		t.Fatalf("error creating %v: %v", gcsPath, err)
	}
	data := "Hello World"
	if _, err := io.Copy(f, strings.NewReader(data)); err != nil {
		t.Fatalf("error writing to %v: %v", gcsPath, err)
	}
	if err := f.Close(); err != nil {
		t.Fatalf("error closing %v: %v", gcsPath, err)
	}

	// Read back from camli-gcs_test.txt
	g, err := wkfs.Open(gcsPath)
	if err != nil {
		t.Fatalf("error opening %v: %v", gcsPath, err)
	}
	defer g.Close()
	var buf bytes.Buffer
	if _, err := io.Copy(&buf, g); err != nil {
		t.Fatalf("error reading %v: %v", gcsPath, err)
	}
	if buf.String() != data {
		t.Fatalf("error with %v contents: got %v, wanted %v", gcsPath, buf.String(), data)
	}
}
Пример #4
0
// KeyIdFromRing returns the public keyId contained in the secret
// ring file secRing. It expects only one keyId in this secret ring
// and returns an error otherwise.
func KeyIdFromRing(secRing string) (keyId string, err error) {
	f, err := wkfs.Open(secRing)
	if err != nil {
		return "", fmt.Errorf("Could not open secret ring file %v: %v", secRing, err)
	}
	defer f.Close()
	el, err := openpgp.ReadKeyRing(f)
	if err != nil {
		return "", fmt.Errorf("Could not read secret ring file %s: %v", secRing, err)
	}
	if len(el) != 1 {
		return "", fmt.Errorf("Secret ring file %v contained %d identities; expected 1", secRing, len(el))
	}
	ent := el[0]
	return ent.PrimaryKey.KeyIdShortString(), nil
}
Пример #5
0
func VerifyPublicKeyFile(file, keyid string) (bool, error) {
	f, err := wkfs.Open(file)
	if err != nil {
		return false, err
	}

	key, err := openArmoredPublicKeyFile(f)
	if err != nil {
		return false, err
	}
	keyId := publicKeyId(key)
	if keyId != strings.ToUpper(keyid) {
		return false, fmt.Errorf("Key in file %q has id %q; expected %q",
			file, keyId, keyid)
	}
	return true, nil
}
Пример #6
0
func publicKeyEntity(keyRing string, keyId string) (*openpgp.Entity, error) {
	f, err := wkfs.Open(keyRing)
	if err != nil {
		return nil, fmt.Errorf("could not open keyRing %v: %v", keyRing, err)
	}
	defer f.Close()
	el, err := openpgp.ReadKeyRing(f)
	if err != nil {
		return nil, err
	}
	for _, e := range el {
		pubk := e.PrimaryKey
		if pubk.KeyIdShortString() == keyId {
			return e, nil
		}
	}
	return nil, fmt.Errorf("keyId %v not found in %v", keyId, keyRing)
}
Пример #7
0
func secretKeyEntity(keyRing string, keyId string) (*openpgp.Entity, error) {
	f, err := wkfs.Open(keyRing)
	if err != nil {
		return nil, fmt.Errorf("could not open keyRing %v: %v", keyRing, err)
	}
	defer f.Close()
	el, err := openpgp.ReadKeyRing(f)
	if err != nil {
		return nil, err
	}
	for _, e := range el {
		pubk := &e.PrivateKey.PublicKey
		// TODO(mpl): decrypt private key if it is passphrase-encrypted
		if pubk.KeyIdShortString() == keyId {
			return e, nil
		}
	}
	return nil, fmt.Errorf("keyId %v not found in %v", keyId, keyRing)
}
Пример #8
0
// EntityFromSecring returns the openpgp Entity from keyFile that matches keyId.
// If empty, keyFile defaults to osutil.SecretRingFile().
func EntityFromSecring(keyId, keyFile string) (*openpgp.Entity, error) {
	if keyId == "" {
		return nil, errors.New("empty keyId passed to EntityFromSecring")
	}
	keyId = strings.ToUpper(keyId)
	if keyFile == "" {
		keyFile = osutil.SecretRingFile()
	}
	secring, err := wkfs.Open(keyFile)
	if err != nil {
		return nil, fmt.Errorf("jsonsign: failed to open keyring: %v", err)
	}
	defer secring.Close()

	el, err := openpgp.ReadKeyRing(secring)
	if err != nil {
		return nil, fmt.Errorf("openpgp.ReadKeyRing of %q: %v", keyFile, err)
	}
	var entity *openpgp.Entity
	for _, e := range el {
		pk := e.PrivateKey
		if pk == nil || (pk.KeyIdString() != keyId && pk.KeyIdShortString() != keyId) {
			continue
		}
		entity = e
	}
	if entity == nil {
		found := []string{}
		for _, e := range el {
			pk := e.PrivateKey
			if pk == nil {
				continue
			}
			found = append(found, pk.KeyIdShortString())
		}
		return nil, fmt.Errorf("didn't find a key in %q for keyId %q; other keyIds in file = %v", keyFile, keyId, found)
	}
	return entity, nil
}
Пример #9
0
func (sr *SignRequest) Sign() (signedJSON string, err error) {
	trimmedJSON := strings.TrimRightFunc(sr.UnsignedJSON, unicode.IsSpace)

	// TODO: make sure these return different things
	inputfail := func(msg string) (string, error) {
		return "", errors.New(msg)
	}
	execfail := func(msg string) (string, error) {
		return "", errors.New(msg)
	}

	jmap := make(map[string]interface{})
	if err := json.Unmarshal([]byte(trimmedJSON), &jmap); err != nil {
		return inputfail("json parse error")
	}

	camliSigner, hasSigner := jmap["camliSigner"]
	if !hasSigner {
		return inputfail("json lacks \"camliSigner\" key with public key blobref")
	}

	camliSignerStr, _ := camliSigner.(string)
	signerBlob, ok := blob.Parse(camliSignerStr)
	if !ok {
		return inputfail("json \"camliSigner\" key is malformed or unsupported")
	}

	pubkeyReader, _, err := sr.Fetcher.Fetch(signerBlob)
	if err != nil {
		// TODO: not really either an inputfail or an execfail.. but going
		// with exec for now.
		return execfail(fmt.Sprintf("failed to find public key %s: %v", signerBlob.String(), err))
	}

	pubk, err := openArmoredPublicKeyFile(pubkeyReader)
	pubkeyReader.Close()
	if err != nil {
		return execfail(fmt.Sprintf("failed to parse public key from blobref %s: %v", signerBlob.String(), err))
	}

	// This check should be redundant if the above JSON parse succeeded, but
	// for explicitness...
	if len(trimmedJSON) == 0 || trimmedJSON[len(trimmedJSON)-1] != '}' {
		return inputfail("json parameter lacks trailing '}'")
	}
	trimmedJSON = trimmedJSON[0 : len(trimmedJSON)-1]

	// sign it
	entityFetcher := sr.EntityFetcher
	if entityFetcher == nil {
		file := sr.secretRingPath()
		if file == "" {
			return "", errors.New("jsonsign: no EntityFetcher, and no secret ring file defined.")
		}
		secring, err := wkfs.Open(sr.secretRingPath())
		if err != nil {
			return "", fmt.Errorf("jsonsign: failed to open secret ring file %q: %v", sr.secretRingPath(), err)
		}
		secring.Close() // just opened to see if it's readable
		entityFetcher = &FileEntityFetcher{File: file}
	}
	signer, err := entityFetcher.FetchEntity(pubk.KeyIdString())
	if err != nil {
		return "", err
	}

	var buf bytes.Buffer
	err = openpgp.ArmoredDetachSign(
		&buf,
		signer,
		strings.NewReader(trimmedJSON),
		&packet.Config{Time: func() time.Time { return sr.SignatureTime }},
	)
	if err != nil {
		return "", err
	}

	output := buf.String()

	index1 := strings.Index(output, "\n\n")
	index2 := strings.Index(output, "\n-----")
	if index1 == -1 || index2 == -1 {
		return execfail("Failed to parse signature from gpg.")
	}
	inner := output[index1+2 : index2]
	signature := strings.Replace(inner, "\n", "", -1)

	return fmt.Sprintf("%s,\"camliSig\":\"%s\"}\n", trimmedJSON, signature), nil
}
Пример #10
0
func (c *ConfigParser) open(filename string) (File, error) {
	if c.Open == nil {
		return wkfs.Open(filename)
	}
	return c.Open(filename)
}