// 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 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) } }
// EncryptShares takes an ordered set of Shamir key share fragments and // PGP public keys and encrypts each Shamir key fragment with the corresponding // public key // // Note: There is no corresponding test function; this functionality is // thoroughly tested in the init and rekey command unit tests func EncryptShares(secretShares [][]byte, pgpKeys []string) ([][]byte, error) { if len(secretShares) != len(pgpKeys) { return nil, fmt.Errorf("Mismatch between number of generated shares and number of PGP keys") } encryptedShares := [][]byte{} for i, 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) } ctBuf := bytes.NewBuffer(nil) pt, err := openpgp.Encrypt(ctBuf, []*openpgp.Entity{entity}, nil, nil, nil) if err != nil { return nil, fmt.Errorf("Error setting up encryption for PGP message: %s", err) } _, err = pt.Write([]byte(hex.EncodeToString(secretShares[i]))) if err != nil { return nil, fmt.Errorf("Error encrypting PGP message: %s", err) } pt.Close() encryptedShares = append(encryptedShares, ctBuf.Bytes()) } return encryptedShares, nil }
// ReadKeyRing reads one or more public/private keys. Unsupported keys are // ignored as long as at least a single valid key is found. func ReadKeyRing(r io.Reader) (el EntityList, err error) { packets := packet.NewReader(r) var lastUnsupportedError error for { var e *Entity e, err = ReadEntity(packets) if err != nil { // TODO: warn about skipped unsupported/unreadable keys if _, ok := err.(errors.UnsupportedError); ok { lastUnsupportedError = err err = readToNextPublicKey(packets) } else if _, ok := err.(errors.StructuralError); ok { // Skip unreadable, badly-formatted keys lastUnsupportedError = err err = readToNextPublicKey(packets) } if err == io.EOF { err = nil break } if err != nil { el = nil break } } else { el = append(el, e) } } if len(el) == 0 && err == nil { err = lastUnsupportedError } return }
func verifyDetachedSignature(key *packet.PublicKey, contentf, sigf io.Reader) error { var hashFunc crypto.Hash packets := packet.NewReader(sigf) p, err := packets.Next() if err != nil { return err } switch sig := p.(type) { case *packet.Signature: hashFunc = sig.Hash case *packet.SignatureV3: hashFunc = sig.Hash default: return errors.UnsupportedError("unrecognized signature") } h := hashFunc.New() if _, err := io.Copy(h, contentf); err != nil && err != io.EOF { return err } switch sig := p.(type) { case *packet.Signature: err = key.VerifySignature(h, sig) case *packet.SignatureV3: err = key.VerifySignatureV3(h, sig) default: panic("unreachable") } return err }
func testSignedManifest(t *testing.T, modify func(*pods.Manifest, *openpgp.Entity)) (*pods.Manifest, *openpgp.Entity) { testManifest := testManifest(t) if fakeSigner == nil { var err error fakeSigner, err = openpgp.ReadEntity(packet.NewReader(bytes.NewReader(fakeEntity))) Assert(t).IsNil(err, "should have read entity") } if modify != nil { modify(testManifest, fakeSigner) } manifestBytes, err := testManifest.Marshal() Assert(t).IsNil(err, "manifest bytes error should have been nil") var buf bytes.Buffer sigWriter, err := clearsign.Encode(&buf, fakeSigner.PrivateKey, nil) Assert(t).IsNil(err, "clearsign Encode error should have been nil") sigWriter.Write(manifestBytes) sigWriter.Close() manifest, err := pods.ManifestFromBytes(buf.Bytes()) Assert(t).IsNil(err, "should have generated manifest from signed bytes") return manifest, fakeSigner }
// loadKey loads a GPG key found at a particular path. func loadKey(keypath string) (*openpgp.Entity, error) { f, err := os.Open(keypath) if err != nil { return nil, err } defer f.Close() pr := packet.NewReader(f) return openpgp.ReadEntity(pr) }
func PublicKeyToPGPClient(publicKey string) PGPClient { block, err := armor.Decode(strings.NewReader(publicKey)) if err != nil { panic(err) } entity, err := openpgp.ReadEntity(packet.NewReader(block.Body)) if err != nil { panic(err) } return PGPClient{openpgp.EntityList{entity}} }
func readPublicSigningKey(keyf io.Reader) (*packet.PublicKey, error) { keypackets := packet.NewReader(keyf) p, err := keypackets.Next() if err != nil { return nil, err } switch pkt := p.(type) { case *packet.PublicKey: debug("key: ", pkt) return pkt, nil default: log.Printf("ReadPublicSigningKey: got %T, want *packet.PublicKey", pkt) } return nil, errors.StructuralError("expected first packet to be PublicKey") }
// 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 }
func encryptEmail(e *Email) error { if len(e.OpenPGPEncryptTo) == 0 { return nil } buf := &bytes.Buffer{} var destEntities []*openpgp.Entity for _, eto := range e.OpenPGPEncryptTo { r := bytes.NewBufferString(eto) blk, err := armor.Decode(r) if err != nil { return err } rr := packet.NewReader(blk.Body) e, err := openpgp.ReadEntity(rr) if err != nil { return err } destEntities = append(destEntities, e) } aew, err := armor.Encode(buf, "PGP MESSAGE", map[string]string{ "Version": "OpenPGP", }) if err != nil { return err } wr, err := openpgp.Encrypt(aew, destEntities, nil, nil, nil) if err != nil { return err } _, err = wr.Write([]byte(e.Body)) if err != nil { wr.Close() return err } wr.Close() aew.Close() e.Body = string(buf.Bytes()) return nil }
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) } }
func newExtPGPPrivateKey(exportedPubKeyStream io.Reader, from string, sign func(content []byte) ([]byte, error)) (*extPGPPrivateKey, error) { var pubKey *packet.PublicKey rd := packet.NewReader(exportedPubKeyStream) for { pkt, err := rd.Next() if err == io.EOF { break } if err != nil { return nil, fmt.Errorf("cannot read exported public key: %v", err) } cand, ok := pkt.(*packet.PublicKey) if ok { if cand.IsSubkey { continue } if pubKey != nil { return nil, fmt.Errorf("cannot select exported public key, found many") } pubKey = cand } } if pubKey == nil { return nil, fmt.Errorf("cannot read exported public key, found none (broken export)") } rsaPubKey, ok := pubKey.PublicKey.(*rsa.PublicKey) if !ok { return nil, fmt.Errorf("not a RSA key") } return &extPGPPrivateKey{ pubKey: RSAPublicKey(rsaPubKey), from: from, pgpFingerprint: fmt.Sprintf("%X", pubKey.Fingerprint), bitLen: rsaPubKey.N.BitLen(), doSign: sign, }, nil }
func (o *openPGP) SetKey(k key) (err error) { keyPath := filepath.Join(conf.mountPoint, k.Path) keyFile, err := os.Open(keyPath) if err != nil { return } defer keyFile.Close() keyBlock, err := armor.Decode(keyFile) if err != nil { return } reader := packet.NewReader(keyBlock.Body) entity, err := openpgp.ReadEntity(reader) if err != nil { return } switch keyBlock.Type { case openpgp.PrivateKeyType: if k.Private != true { return fmt.Errorf("public key detected in private key slot") } o.secKey = entity case openpgp.PublicKeyType: if k.Private == true { return fmt.Errorf("private key detected in public key slot") } o.pubKey = entity default: return fmt.Errorf("key type error: %s", keyBlock.Type) } return }
// Import private key from defined path. func Import(privKeyPath string) (*PGP, error) { privKeyFile, err := os.Open(privKeyPath) if err != nil { return nil, err } defer privKeyFile.Close() file := packet.NewReader(bufio.NewReader(privKeyFile)) entity, err := openpgp.ReadEntity(file) if err != nil { return nil, errwrap.Wrapf(err, "can't read entity from path") } obj := &PGP{ Entity: entity, } log.Printf("PGP: Imported key: %s", obj.Entity.PrivateKey.KeyIdShortString()) return obj, nil }
// 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 }
// ParsePublicKey parses the given public key file func ParsePublicKey(keyPath string) (*openpgp.Entity, error) { f, err := os.Open(keyPath) if err != nil { return nil, err } defer f.Close() // Parse our key key, err := armor.Decode(f) if err != nil { return nil, err } if key.Type != openpgp.PublicKeyType { return nil, fmt.Errorf("Key of wrong type:%s", key.Type) } r := packet.NewReader(key.Body) to, err := openpgp.ReadEntity(r) if err != nil { return nil, err } return to, nil }
// CheckDetachedSignature takes a signed file and a detached signature and // returns the signer if the signature is valid. If the signer isn't known, // ErrUnknownIssuer is returned. func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) { var issuerKeyId uint64 var hashFunc crypto.Hash var sigType packet.SignatureType var keys []Key var p packet.Packet packets := packet.NewReader(signature) for { p, err = packets.Next() if err == io.EOF { return nil, errors.ErrUnknownIssuer } if err != nil { return nil, err } switch sig := p.(type) { case *packet.Signature: if sig.IssuerKeyId == nil { return nil, errors.StructuralError("signature doesn't have an issuer") } issuerKeyId = *sig.IssuerKeyId hashFunc = sig.Hash sigType = sig.SigType case *packet.SignatureV3: issuerKeyId = sig.IssuerKeyId hashFunc = sig.Hash sigType = sig.SigType default: return nil, errors.StructuralError("non signature packet found") } keys = keyring.KeysByIdUsage(issuerKeyId, packet.KeyFlagSign) if len(keys) > 0 { break } } if len(keys) == 0 { panic("unreachable") } h, wrappedHash, err := hashForSignature(hashFunc, sigType) if err != nil { return nil, err } if _, err := io.Copy(wrappedHash, signed); err != nil && err != io.EOF { return nil, err } for _, key := range keys { switch sig := p.(type) { case *packet.Signature: err = key.PublicKey.VerifySignature(h, sig) case *packet.SignatureV3: err = key.PublicKey.VerifySignatureV3(h, sig) default: panic("unreachable") } if err == nil { return key.Entity, nil } } return nil, err }
func main2() { // open ascii armored private key from, err := os.Open("my.asc.key") logging.CheckFatal(err) defer from.Close() // decode armor and check key type fromBlock, err := armor.Decode(from) logging.CheckFatal(err) if fromBlock.Type != openpgp.PrivateKeyType { logging.CheckFatal(fmt.Errorf("from key type:%s", fromBlock.Type)) } // parse and decrypt decoded key fromReader := packet.NewReader(fromBlock.Body) fromEntity, err := openpgp.ReadEntity(fromReader) logging.CheckFatal(err) log.Println("Enter Key Passphrase:") pw, err := terminal.ReadPassword(0) logging.CheckFatal(err) err = fromEntity.PrivateKey.Decrypt(pw) logging.CheckFatal(err) // open destination key (no ascii armor here) to, err := os.Open("mkd.pubkey") logging.CheckFatal(err) defer to.Close() toReader := packet.NewReader(to) toEntity, err := openpgp.ReadEntity(toReader) logging.CheckFatal(err) log.Printf("to: %x", toEntity.PrimaryKey.Fingerprint) log.Printf("from: %x", fromEntity.PrimaryKey.Fingerprint) // output file out, err := os.Create("out.enc") logging.CheckFatal(err) defer out.Close() hints := &openpgp.FileHints{ IsBinary: true, FileName: "test.zip", ModTime: time.Now(), } // prepare encryption pipe encOut, err := openpgp.Encrypt(out, []*openpgp.Entity{toEntity}, fromEntity, hints, nil) logging.CheckFatal(err) // for fun, lets write a zip file to it created inline zipW := zip.NewWriter(encOut) t1, err := zipW.Create("test1.de.txt") logging.CheckFatal(err) fmt.Fprintln(t1, "Hallo Welt") t2, err := zipW.Create("test1.en.txt") logging.CheckFatal(err) fmt.Fprintln(t2, "Hello World - the 2nd") logging.CheckFatal(zipW.Flush()) logging.CheckFatal(zipW.Close()) // close the encPipe to finish the process logging.CheckFatal(encOut.Close()) }
// ReadMessage parses an OpenPGP message that may be signed and/or encrypted. // The given KeyRing should contain both public keys (for signature // verification) and, possibly encrypted, private keys for decrypting. // If config is nil, sensible defaults will be used. func ReadMessage(r io.Reader, keyring KeyRing, prompt PromptFunction, config *packet.Config) (md *MessageDetails, err error) { var p packet.Packet var symKeys []*packet.SymmetricKeyEncrypted var pubKeys []keyEnvelopePair var se *packet.SymmetricallyEncrypted packets := packet.NewReader(r) md = new(MessageDetails) md.IsEncrypted = true // The message, if encrypted, starts with a number of packets // containing an encrypted decryption key. The decryption key is either // encrypted to a public key, or with a passphrase. This loop // collects these packets. ParsePackets: for { p, err = packets.Next() if err != nil { return nil, err } switch p := p.(type) { case *packet.SymmetricKeyEncrypted: // This packet contains the decryption key encrypted with a passphrase. md.IsSymmetricallyEncrypted = true symKeys = append(symKeys, p) case *packet.EncryptedKey: // This packet contains the decryption key encrypted to a public key. md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId) switch p.Algo { case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal: break default: continue } var keys []Key if p.KeyId == 0 { keys = keyring.DecryptionKeys() } else { keys = keyring.KeysById(p.KeyId) } for _, k := range keys { pubKeys = append(pubKeys, keyEnvelopePair{k, p}) } case *packet.SymmetricallyEncrypted: se = p break ParsePackets case *packet.Compressed, *packet.LiteralData, *packet.OnePassSignature: // This message isn't encrypted. if len(symKeys) != 0 || len(pubKeys) != 0 { return nil, errors.StructuralError("key material not followed by encrypted message") } packets.Unread(p) return readSignedMessage(packets, nil, keyring) } } var candidates []Key var decrypted io.ReadCloser // Now that we have the list of encrypted keys we need to decrypt at // least one of them or, if we cannot, we need to call the prompt // function so that it can decrypt a key or give us a passphrase. FindKey: for { // See if any of the keys already have a private key available candidates = candidates[:0] candidateFingerprints := make(map[string]bool) for _, pk := range pubKeys { if pk.key.PrivateKey == nil { continue } if !pk.key.PrivateKey.Encrypted { if len(pk.encryptedKey.Key) == 0 { pk.encryptedKey.Decrypt(pk.key.PrivateKey, config) } if len(pk.encryptedKey.Key) == 0 { continue } decrypted, err = se.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key) if err != nil && err != errors.ErrKeyIncorrect { return nil, err } if decrypted != nil { md.DecryptedWith = pk.key break FindKey } } else { fpr := string(pk.key.PublicKey.Fingerprint[:]) if v := candidateFingerprints[fpr]; v { continue } candidates = append(candidates, pk.key) candidateFingerprints[fpr] = true } } if len(candidates) == 0 && len(symKeys) == 0 { return nil, errors.ErrKeyIncorrect } if prompt == nil { return nil, errors.ErrKeyIncorrect } passphrase, err := prompt(candidates, len(symKeys) != 0) if err != nil { return nil, err } // Try the symmetric passphrase first if len(symKeys) != 0 && passphrase != nil { for _, s := range symKeys { err = s.Decrypt(passphrase) if err == nil && !s.Encrypted { decrypted, err = se.Decrypt(s.CipherFunc, s.Key) if err != nil && err != errors.ErrKeyIncorrect { return nil, err } if decrypted != nil { break FindKey } } } } } md.decrypted = decrypted if err := packets.Push(decrypted); err != nil { return nil, err } return readSignedMessage(packets, md, keyring) }
func parseDecryptAndTestUnsealKeys(t *testing.T, input, rootToken string, fingerprints bool, backupKeys map[string][]string, core *vault.Core) { decoder := base64.StdEncoding priv1Bytes, err := decoder.DecodeString(privKey1) if err != nil { t.Fatalf("Error decoding bytes for private key 1: %s", err) } priv2Bytes, err := decoder.DecodeString(privKey2) if err != nil { t.Fatalf("Error decoding bytes for private key 2: %s", err) } priv3Bytes, err := decoder.DecodeString(privKey3) if err != nil { t.Fatalf("Error decoding bytes for private key 3: %s", err) } privBytes := [][]byte{ priv1Bytes, priv2Bytes, priv3Bytes, } 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) != 3 { 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 backupKeys != 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, backupKeys) { t.Fatalf("test map and backup map do not match, test map is\n%#v\nbackup map is\n%#v", testMap, backupKeys) } } unsealKeys := []string{} ptBuf := bytes.NewBuffer(nil) for i, keyHex := range privBytes { if i > 2 { break } ptBuf.Reset() entity, err := openpgp.ReadEntity(packet.NewReader(bytes.NewBuffer(keyHex))) if err != nil { t.Fatalf("Error parsing private key %d: %s", i, err) } keyBytes, err := hex.DecodeString(encodedKeys[i]) if err != nil { t.Fatalf("Error hex-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") } } }
func parseDecryptAndTestUnsealKeys(t *testing.T, input, rootToken string, core *vault.Core) { decoder := base64.StdEncoding priv1Bytes, err := decoder.DecodeString(privKey1) if err != nil { t.Fatalf("Error decoding bytes for private key 1: %s", err) } priv2Bytes, err := decoder.DecodeString(privKey2) if err != nil { t.Fatalf("Error decoding bytes for private key 2: %s", err) } priv3Bytes, err := decoder.DecodeString(privKey3) if err != nil { t.Fatalf("Error decoding bytes for private key 3: %s", err) } privBytes := [][]byte{ priv1Bytes, priv2Bytes, priv3Bytes, } 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) != 3 { 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{} for _, pair := range matches { if len(pair) != 2 { t.Fatalf("Key not found: %#v", pair) } encodedKeys = append(encodedKeys, pair[1]) } unsealKeys := []string{} ptBuf := bytes.NewBuffer(nil) for i, keyHex := range privBytes { if i > 2 { break } ptBuf.Reset() entity, err := openpgp.ReadEntity(packet.NewReader(bytes.NewBuffer(keyHex))) if err != nil { t.Fatalf("Error parsing private key %d: %s", i, err) } keyBytes, err := hex.DecodeString(encodedKeys[i]) if err != nil { t.Fatalf("Error hex-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") } } }