// 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 }
func PGPDecrypt(source io.Reader, sink io.Writer, kr openpgp.KeyRing) (*SignatureStatus, error) { peeker := NewPeeker(source) var r io.Reader r = peeker armored, clearsigned := PGPDetect(peeker) if clearsigned { return pgpDecryptClearsign(peeker, sink, kr) } if armored { b, err := armor.Decode(r) if err != nil { return nil, err } r = b.Body } G.Log.Debug("Calling into openpgp ReadMessage for decryption") md, err := openpgp.ReadMessage(r, kr, nil, nil) if err != nil { if err == errors.ErrKeyIncorrect { return nil, PGPNoDecryptionKeyError{Msg: "unable to find decryption key for this message"} } return nil, err } if md.IsSigned { G.Log.Debug("message is signed (SignedByKeyId: %+v) (have key? %v)", md.SignedByKeyId, md.SignedBy != nil) } n, err := io.Copy(sink, md.UnverifiedBody) if err != nil { return nil, err } G.Log.Debug("PGPDecrypt: copied %d bytes to writer", n) var status SignatureStatus if md.IsSigned { status.IsSigned = true status.KeyID = md.SignedByKeyId if md.Signature != nil { status.SignatureTime = md.Signature.CreationTime } if md.SignedBy != nil { status.Entity = md.SignedBy.Entity } if md.SignatureError != nil { status.SignatureError = md.SignatureError } else { status.Verified = true } } status.RecipientKeyIDs = md.EncryptedToKeyIds return &status, nil }
func TestPGPEncryptLong(t *testing.T) { tc := SetupTest(t, "pgp_encrypt", 1) defer tc.Cleanup() bundleSrc, err := tc.MakePGPKey("*****@*****.**") if err != nil { t.Fatal(err) } bundleDst, err := tc.MakePGPKey("*****@*****.**") if err != nil { t.Fatal(err) } msg := make([]byte, 1024*1024) rand.Read(msg) G.Log.Info("msg size: %d", len(msg)) sink := NewBufferCloser() recipients := []*PGPKeyBundle{bundleSrc, bundleDst} if err := PGPEncrypt(bytes.NewReader(msg), sink, bundleSrc, recipients); err != nil { t.Fatal(err) } out := sink.Bytes() if len(out) == 0 { t.Fatal("no output") } // check that each recipient can read the message for _, recip := range recipients { kr := openpgp.EntityList{recip.Entity} emsg := bytes.NewBuffer(out) md, err := openpgp.ReadMessage(emsg, kr, nil, nil) if err != nil { t.Fatal(err) } text, err := ioutil.ReadAll(md.UnverifiedBody) if err != nil { t.Fatal(err) } if string(text) != string(msg) { t.Errorf("message: %q, expected %q", string(text), string(msg)) } } }
func TestPGPEncryptQuick(t *testing.T) { tc := SetupTest(t, "pgp_encrypt", 1) defer tc.Cleanup() bundleSrc, err := tc.MakePGPKey("*****@*****.**") if err != nil { t.Fatal(err) } bundleDst, err := tc.MakePGPKey("*****@*****.**") if err != nil { t.Fatal(err) } f := func(msg []byte) bool { sink := NewBufferCloser() recipients := []*PGPKeyBundle{bundleSrc, bundleDst} if err := PGPEncrypt(bytes.NewReader(msg), sink, bundleSrc, recipients); err != nil { return false } out := sink.Bytes() if len(out) == 0 { return false } // check that each recipient can read the message for _, recip := range recipients { kr := openpgp.EntityList{recip.Entity} emsg := bytes.NewBuffer(out) md, err := openpgp.ReadMessage(emsg, kr, nil, nil) if err != nil { return false } data, err := ioutil.ReadAll(md.UnverifiedBody) if err != nil { return false } if !bytes.Equal(data, msg) { return false } } return true } if err := quick.Check(f, nil); err != nil { t.Error(err) } }
func (ps *ParsedSig) AssertPayload(expected []byte) error { ring := EmptyKeyRing{} md, err := openpgp.ReadMessage(bytes.NewReader(ps.SigBody), ring, nil, nil) if err != nil { return err } data, err := ioutil.ReadAll(md.UnverifiedBody) if err != nil { return err } if !FastByteArrayEq(data, expected) { err = fmt.Errorf("Signature did not contain expected text") return err } return nil }
func TestPGPEncryptString(t *testing.T) { tc := SetupTest(t, "pgp_encrypt", 1) defer tc.Cleanup() bundleSrc, err := tc.MakePGPKey("*****@*****.**") if err != nil { t.Fatal(err) } bundleDst, err := tc.MakePGPKey("*****@*****.**") if err != nil { t.Fatal(err) } msg := "59 seconds" recipients := []*PGPKeyBundle{bundleSrc, bundleDst} out, err := PGPEncryptString(msg, bundleSrc, recipients) if err != nil { t.Fatal(err) } if len(out) == 0 { t.Fatal("no output") } // check that each recipient can read the message for _, recip := range recipients { kr := openpgp.EntityList{recip.Entity} emsg := bytes.NewBuffer(out) md, err := openpgp.ReadMessage(emsg, kr, nil, nil) if err != nil { t.Fatal(err) } text, err := ioutil.ReadAll(md.UnverifiedBody) if err != nil { t.Fatal(err) } if string(text) != msg { t.Errorf("message: %q, expected %q", string(text), msg) } } }
func (ps *ParsedSig) Verify(k PGPKeyBundle) (err error) { ps.MD, err = openpgp.ReadMessage(bytes.NewReader(ps.SigBody), k, nil, nil) if err != nil { return } if !ps.MD.IsSigned || ps.MD.SignedBy == nil { err = fmt.Errorf("Message wasn't signed") return } if !k.MatchesKey(ps.MD.SignedBy) { err = fmt.Errorf("Got wrong SignedBy key %v", hex.EncodeToString(ps.MD.SignedBy.PublicKey.Fingerprint[:])) return } if ps.MD.UnverifiedBody == nil { err = fmt.Errorf("no signed material found") return } ps.LiteralData, err = ioutil.ReadAll(ps.MD.UnverifiedBody) if err != nil { return } // We'll see a sig error here after reading in the UnverifiedBody above, // if there was one to see. if err = ps.MD.SignatureError; err != nil { return } if ps.MD.Signature == nil && ps.MD.SignatureV3 == nil { err = fmt.Errorf("No available signature after checking signature") return } // Hopefully by here we've covered all of our bases. return nil }
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) }
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") } }
func PGPDecrypt(g *GlobalContext, source io.Reader, sink io.Writer, kr openpgp.KeyRing) (*SignatureStatus, error) { var sc StreamClassification var err error sc, source, err = ClassifyStream(source) if err != nil { return nil, err } if sc.Format != CryptoMessageFormatPGP { return nil, WrongCryptoFormatError{ Wanted: CryptoMessageFormatPGP, Received: sc.Format, Operation: "decrypt", } } if sc.Type == CryptoMessageTypeClearSignature { return pgpDecryptClearsign(g, source, sink, kr) } if sc.Armored { b, err := armor.Decode(source) if err != nil { return nil, err } source = b.Body } g.Log.Debug("Calling into openpgp ReadMessage for decryption") md, err := openpgp.ReadMessage(source, kr, nil, nil) if err != nil { if err == errors.ErrKeyIncorrect { return nil, NoDecryptionKeyError{Msg: "unable to find a PGP decryption key for this message"} } return nil, err } if md.IsSigned { g.Log.Debug("message is signed (SignedByKeyId: %+v) (have key? %v)", md.SignedByKeyId, md.SignedBy != nil) } n, err := io.Copy(sink, md.UnverifiedBody) if err != nil { return nil, err } g.Log.Debug("PGPDecrypt: copied %d bytes to writer", n) var status SignatureStatus if md.IsSigned { status.IsSigned = true status.KeyID = md.SignedByKeyId if md.Signature != nil { status.SignatureTime = md.Signature.CreationTime } if md.SignedBy != nil { status.Entity = md.SignedBy.Entity } if md.SignatureError != nil { status.SignatureError = md.SignatureError } else { status.Verified = true } } status.RecipientKeyIDs = md.EncryptedToKeyIds return &status, nil }