Exemple #1
0
// DecryptBytes takes in base64-encoded encrypted bytes and the base64-encoded
// private key and decrypts it. A bytes.Buffer is returned to allow the caller
// to do useful thing with it (get it as a []byte, get it as a string, use it
// as an io.Reader, etc), and also because this function doesn't know if what
// comes out is binary data or a string, so let the caller decide.
func DecryptBytes(encodedCrypt, privKey string) (*bytes.Buffer, error) {
	privKeyBytes, err := base64.StdEncoding.DecodeString(privKey)
	if err != nil {
		return nil, fmt.Errorf("Error decoding base64 private key: %s", err)
	}

	cryptBytes, err := base64.StdEncoding.DecodeString(encodedCrypt)
	if err != nil {
		return nil, fmt.Errorf("Error decoding base64 crypted bytes: %s", err)
	}

	entity, err := openpgp.ReadEntity(packet.NewReader(bytes.NewBuffer(privKeyBytes)))
	if err != nil {
		return nil, fmt.Errorf("Error parsing private key: %s", err)
	}

	entityList := &openpgp.EntityList{entity}
	md, err := openpgp.ReadMessage(bytes.NewBuffer(cryptBytes), entityList, nil, nil)
	if err != nil {
		return nil, fmt.Errorf("Error decrypting the messages: %s", err)
	}

	ptBuf := bytes.NewBuffer(nil)
	ptBuf.ReadFrom(md.UnverifiedBody)

	return ptBuf, nil
}
Exemple #2
0
func TestFetchKeybasePubkeys(t *testing.T) {
	testset := []string{"keybase:jefferai", "keybase:hashicorp"}
	ret, err := FetchKeybasePubkeys(testset)
	if err != nil {
		t.Fatalf("bad: %v", err)
	}

	fingerprints := []string{}
	for _, user := range testset {
		data, err := base64.StdEncoding.DecodeString(ret[user])
		if err != nil {
			t.Fatalf("error decoding key for user %s: %v", user, err)
		}
		entity, err := openpgp.ReadEntity(packet.NewReader(bytes.NewBuffer(data)))
		if err != nil {
			t.Fatalf("error parsing key for user %s: %v", user, err)
		}
		fingerprints = append(fingerprints, hex.EncodeToString(entity.PrimaryKey.Fingerprint[:]))
	}

	exp := []string{
		"0f801f518ec853daff611e836528efcac6caa3db",
		"91a6e7f85d05c65630bef18951852d87348ffc4c",
	}

	if !reflect.DeepEqual(fingerprints, exp) {
		t.Fatalf("fingerprints do not match; expected \n%#v\ngot\n%#v\n", exp, fingerprints)
	}
}
Exemple #3
0
// GetEntities takes in a string array of base64-encoded PGP keys and returns
// the openpgp Entities
func GetEntities(pgpKeys []string) ([]*openpgp.Entity, error) {
	ret := make([]*openpgp.Entity, 0, len(pgpKeys))
	for _, keystring := range pgpKeys {
		data, err := base64.StdEncoding.DecodeString(keystring)
		if err != nil {
			return nil, fmt.Errorf("Error decoding given PGP key: %s", err)
		}
		entity, err := openpgp.ReadEntity(packet.NewReader(bytes.NewBuffer(data)))
		if err != nil {
			return nil, fmt.Errorf("Error parsing given PGP key: %s", err)
		}
		ret = append(ret, entity)
	}
	return ret, nil
}
Exemple #4
0
func TestPubKeyFilesFlagSetKeybase(t *testing.T) {
	tempDir, err := ioutil.TempDir("", "vault-test")
	if err != nil {
		t.Fatalf("Error creating temporary directory: %s", err)
	}
	defer os.RemoveAll(tempDir)

	err = ioutil.WriteFile(tempDir+"/pubkey2", []byte(pubKey2), 0755)
	if err != nil {
		t.Fatalf("Error writing pub key 2 to temp file: %s", err)
	}

	pkf := new(PubKeyFilesFlag)
	err = pkf.Set("keybase:jefferai,@" + tempDir + "/pubkey2" + ",keybase:hashicorp")
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	fingerprints := []string{}
	for _, pubkey := range []string(*pkf) {
		keyBytes, err := base64.StdEncoding.DecodeString(pubkey)
		if err != nil {
			t.Fatalf("bad: %v", err)
		}
		pubKeyBuf := bytes.NewBuffer(keyBytes)
		reader := packet.NewReader(pubKeyBuf)
		entity, err := openpgp.ReadEntity(reader)
		if err != nil {
			t.Fatalf("bad: %v", err)
		}
		if entity == nil {
			t.Fatalf("nil entity encountered")
		}
		fingerprints = append(fingerprints, hex.EncodeToString(entity.PrimaryKey.Fingerprint[:]))
	}

	exp := []string{
		"0f801f518ec853daff611e836528efcac6caa3db",
		"cf3d4694c9f57b28cb4092c2eb832c67eb5e8957",
		"91a6e7f85d05c65630bef18951852d87348ffc4c",
	}

	if !reflect.DeepEqual(fingerprints, exp) {
		t.Fatalf("bad: got \n%#v\nexpected\n%#v\n", fingerprints, exp)
	}
}
Exemple #5
0
// Validate is used to sanity check the seal configuration
func (s *SealConfig) Validate() error {
	if s.SecretShares < 1 {
		return fmt.Errorf("shares must be at least one")
	}
	if s.SecretThreshold < 1 {
		return fmt.Errorf("threshold must be at least one")
	}
	if s.SecretShares > 1 && s.SecretThreshold == 1 {
		return fmt.Errorf("threshold must be greater than one for multiple shares")
	}
	if s.SecretShares > 255 {
		return fmt.Errorf("shares must be less than 256")
	}
	if s.SecretThreshold > 255 {
		return fmt.Errorf("threshold must be less than 256")
	}
	if s.SecretThreshold > s.SecretShares {
		return fmt.Errorf("threshold cannot be larger than shares")
	}
	if s.StoredShares > s.SecretShares {
		return fmt.Errorf("stored keys cannot be larger than shares")
	}
	if len(s.PGPKeys) > 0 && len(s.PGPKeys) != s.SecretShares-s.StoredShares {
		return fmt.Errorf("count mismatch between number of provided PGP keys and number of shares")
	}
	if len(s.PGPKeys) > 0 {
		for _, keystring := range s.PGPKeys {
			data, err := base64.StdEncoding.DecodeString(keystring)
			if err != nil {
				return fmt.Errorf("Error decoding given PGP key: %s", err)
			}
			_, err = openpgp.ReadEntity(packet.NewReader(bytes.NewBuffer(data)))
			if err != nil {
				return fmt.Errorf("Error parsing given PGP key: %s", err)
			}
		}
	}
	return nil
}
Exemple #6
0
func parseDecryptAndTestUnsealKeys(t *testing.T,
	input, rootToken string,
	fingerprints bool,
	backupKeys map[string][]string,
	backupKeysB64 map[string][]string,
	core *vault.Core) {

	decoder := base64.StdEncoding
	priv1Bytes, err := decoder.DecodeString(pgpkeys.TestPrivKey1)
	if err != nil {
		t.Fatalf("Error decoding bytes for private key 1: %s", err)
	}
	priv2Bytes, err := decoder.DecodeString(pgpkeys.TestPrivKey2)
	if err != nil {
		t.Fatalf("Error decoding bytes for private key 2: %s", err)
	}
	priv3Bytes, err := decoder.DecodeString(pgpkeys.TestPrivKey3)
	if err != nil {
		t.Fatalf("Error decoding bytes for private key 3: %s", err)
	}

	privBytes := [][]byte{
		priv1Bytes,
		priv2Bytes,
		priv3Bytes,
	}

	testFunc := func(bkeys map[string][]string) {
		var re *regexp.Regexp
		if fingerprints {
			re, err = regexp.Compile("\\s*Key\\s+\\d+\\s+fingerprint:\\s+([0-9a-fA-F]+);\\s+value:\\s+(.*)")
		} else {
			re, err = regexp.Compile("\\s*Key\\s+\\d+:\\s+(.*)")
		}
		if err != nil {
			t.Fatalf("Error compiling regex: %s", err)
		}
		matches := re.FindAllStringSubmatch(input, -1)
		if len(matches) != 4 {
			t.Fatalf("Unexpected number of keys returned, got %d, matches was \n\n%#v\n\n, input was \n\n%s\n\n", len(matches), matches, input)
		}

		encodedKeys := []string{}
		matchedFingerprints := []string{}
		for _, tuple := range matches {
			if fingerprints {
				if len(tuple) != 3 {
					t.Fatalf("Key not found: %#v", tuple)
				}
				matchedFingerprints = append(matchedFingerprints, tuple[1])
				encodedKeys = append(encodedKeys, tuple[2])
			} else {
				if len(tuple) != 2 {
					t.Fatalf("Key not found: %#v", tuple)
				}
				encodedKeys = append(encodedKeys, tuple[1])
			}
		}

		if bkeys != nil && len(matchedFingerprints) != 0 {
			testMap := map[string][]string{}
			for i, v := range matchedFingerprints {
				testMap[v] = append(testMap[v], encodedKeys[i])
				sort.Strings(testMap[v])
			}
			if !reflect.DeepEqual(testMap, bkeys) {
				t.Fatalf("test map and backup map do not match, test map is\n%#v\nbackup map is\n%#v", testMap, bkeys)
			}
		}

		unsealKeys := []string{}
		ptBuf := bytes.NewBuffer(nil)
		for i, privKeyBytes := range privBytes {
			if i > 2 {
				break
			}
			ptBuf.Reset()
			entity, err := openpgp.ReadEntity(packet.NewReader(bytes.NewBuffer(privKeyBytes)))
			if err != nil {
				t.Fatalf("Error parsing private key %d: %s", i, err)
			}
			var keyBytes []byte
			keyBytes, err = base64.StdEncoding.DecodeString(encodedKeys[i])
			if err != nil {
				t.Fatalf("Error decoding key %d: %s", i, err)
			}
			entityList := &openpgp.EntityList{entity}
			md, err := openpgp.ReadMessage(bytes.NewBuffer(keyBytes), entityList, nil, nil)
			if err != nil {
				t.Fatalf("Error decrypting with key %d (%s): %s", i, encodedKeys[i], err)
			}
			ptBuf.ReadFrom(md.UnverifiedBody)
			unsealKeys = append(unsealKeys, ptBuf.String())
		}

		err = core.Seal(rootToken)
		if err != nil {
			t.Fatalf("Error sealing vault with provided root token: %s", err)
		}

		for i, unsealKey := range unsealKeys {
			unsealBytes, err := hex.DecodeString(unsealKey)
			if err != nil {
				t.Fatalf("Error hex decoding unseal key %s: %s", unsealKey, err)
			}
			unsealed, err := core.Unseal(unsealBytes)
			if err != nil {
				t.Fatalf("Error using unseal key %s: %s", unsealKey, err)
			}
			if i >= 2 && !unsealed {
				t.Fatalf("Error: Provided two unseal keys but core is not unsealed")
			}
		}
	}

	testFunc(backupKeysB64)
}
Exemple #7
0
func TestInit_PGP(t *testing.T) {
	ui := new(cli.MockUi)
	c := &InitCommand{
		Meta: meta.Meta{
			Ui: ui,
		},
	}

	core := vault.TestCore(t)
	ln, addr := http.TestServer(t, core)
	defer ln.Close()

	init, err := core.Initialized()
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if init {
		t.Fatal("should not be initialized")
	}

	tempDir, pubFiles, err := getPubKeyFiles(t)
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	args := []string{
		"-address", addr,
		"-key-shares", "2",
		"-pgp-keys", pubFiles[0] + ",@" + pubFiles[1] + "," + pubFiles[2],
		"-key-threshold", "2",
		"-root-token-pgp-key", pubFiles[0],
	}

	// This should fail, as key-shares does not match pgp-keys size
	if code := c.Run(args); code == 0 {
		t.Fatalf("bad (command should have failed): %d\n\n%s", code, ui.ErrorWriter.String())
	}

	args = []string{
		"-address", addr,
		"-key-shares", "4",
		"-pgp-keys", pubFiles[0] + ",@" + pubFiles[1] + "," + pubFiles[2] + "," + pubFiles[3],
		"-key-threshold", "2",
		"-root-token-pgp-key", pubFiles[0],
	}

	ui.OutputWriter.Reset()

	if code := c.Run(args); code != 0 {
		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
	}

	init, err = core.Initialized()
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if !init {
		t.Fatal("should be initialized")
	}

	sealConf, err := core.SealAccess().BarrierConfig()
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	pgpKeys := []string{}
	for _, pubFile := range pubFiles {
		pub, err := pgpkeys.ReadPGPFile(pubFile)
		if err != nil {
			t.Fatalf("bad: %v", err)
		}
		pgpKeys = append(pgpKeys, pub)
	}

	expected := &vault.SealConfig{
		Type:            "shamir",
		SecretShares:    4,
		SecretThreshold: 2,
		PGPKeys:         pgpKeys,
	}
	if !reflect.DeepEqual(expected, sealConf) {
		t.Fatalf("expected:\n%#v\ngot:\n%#v\n", expected, sealConf)
	}

	re, err := regexp.Compile("\\s+Initial Root Token:\\s+(.*)")
	if err != nil {
		t.Fatalf("Error compiling regex: %s", err)
	}
	matches := re.FindAllStringSubmatch(ui.OutputWriter.String(), -1)
	if len(matches) != 1 {
		t.Fatalf("Unexpected number of tokens found, got %d", len(matches))
	}

	encRootToken := matches[0][1]
	privKeyBytes, err := base64.StdEncoding.DecodeString(pgpkeys.TestPrivKey1)
	if err != nil {
		t.Fatalf("error decoding private key: %v", err)
	}
	ptBuf := bytes.NewBuffer(nil)
	entity, err := openpgp.ReadEntity(packet.NewReader(bytes.NewBuffer(privKeyBytes)))
	if err != nil {
		t.Fatalf("Error parsing private key: %s", err)
	}
	var rootBytes []byte
	rootBytes, err = base64.StdEncoding.DecodeString(encRootToken)
	if err != nil {
		t.Fatalf("Error decoding root token: %s", err)
	}
	entityList := &openpgp.EntityList{entity}
	md, err := openpgp.ReadMessage(bytes.NewBuffer(rootBytes), entityList, nil, nil)
	if err != nil {
		t.Fatalf("Error decrypting root token: %s", err)
	}
	ptBuf.ReadFrom(md.UnverifiedBody)
	rootToken := ptBuf.String()

	parseDecryptAndTestUnsealKeys(t, ui.OutputWriter.String(), rootToken, false, nil, nil, core)

	client, err := c.Client()
	if err != nil {
		t.Fatalf("Error fetching client: %v", err)
	}

	client.SetToken(rootToken)

	tokenInfo, err := client.Auth().Token().LookupSelf()
	if err != nil {
		t.Fatalf("Error looking up root token info: %v", err)
	}

	if tokenInfo.Data["policies"].([]interface{})[0].(string) != "root" {
		t.Fatalf("expected root policy")
	}
}