// GetKeyAES returns the RSA private key of the record given the correct password. func (pr PasswordRecord) GetKeyRSA(password string) (key rsa.PrivateKey, err error) { if pr.Type != RSARecord { return key, errors.New("Invalid function for record type") } err = pr.ValidatePassword(password) if err != nil { return } passKey, err := derivePasswordKey(password, pr.KeySalt) if err != nil { return } rsaExponentPadded, err := decryptCBC(pr.RSAKey.RSAExp, pr.RSAKey.RSAExpIV, passKey) if err != nil { return } rsaExponent, err := padding.RemovePadding(rsaExponentPadded) if err != nil { return } rsaPrimePPadded, err := decryptCBC(pr.RSAKey.RSAPrimeP, pr.RSAKey.RSAPrimePIV, passKey) if err != nil { return } rsaPrimeP, err := padding.RemovePadding(rsaPrimePPadded) if err != nil { return } rsaPrimeQPadded, err := decryptCBC(pr.RSAKey.RSAPrimeQ, pr.RSAKey.RSAPrimeQIV, passKey) if err != nil { return } rsaPrimeQ, err := padding.RemovePadding(rsaPrimeQPadded) if err != nil { return } key.PublicKey = pr.RSAKey.RSAPublic key.D = big.NewInt(0).SetBytes(rsaExponent) key.Primes = []*big.Int{big.NewInt(0), big.NewInt(0)} key.Primes[0].SetBytes(rsaPrimeP) key.Primes[1].SetBytes(rsaPrimeQ) err = key.Validate() if err != nil { return } return }
// GetKeyECC returns the ECDSA private key of the record given the correct password. func (pr PasswordRecord) GetKeyECC(password string) (key *ecdsa.PrivateKey, err error) { if pr.Type != ECCRecord { return key, errors.New("Invalid function for record type") } if err = pr.ValidatePassword(password); err != nil { return } passKey, err := derivePasswordKey(password, pr.KeySalt) if err != nil { return } x509Padded, err := symcrypt.DecryptCBC(pr.ECKey.ECPriv, pr.ECKey.ECPrivIV, passKey) if err != nil { return } ecX509, err := padding.RemovePadding(x509Padded) if err != nil { return } return x509.ParseECPrivateKey(ecX509) }
// Decrypt authentications and recovers the original message from // its input using the private key and the ephemeral key included in // the message. func Decrypt(priv *ecdsa.PrivateKey, in []byte) (out []byte, err error) { ephLen := int(in[0]) ephPub := in[1 : 1+ephLen] ct := in[1+ephLen:] if len(ct) < (sha1.Size + aes.BlockSize) { return nil, errors.New("Invalid ciphertext") } x, y := elliptic.Unmarshal(Curve(), ephPub) if x == nil { return nil, errors.New("Invalid public key") } x, _ = priv.Curve.ScalarMult(x, y, priv.D.Bytes()) if x == nil { return nil, errors.New("Failed to generate encryption key") } shared := sha256.Sum256(x.Bytes()) tagStart := len(ct) - sha1.Size h := hmac.New(sha1.New, shared[16:]) h.Write(ct[:tagStart]) mac := h.Sum(nil) if !hmac.Equal(mac, ct[tagStart:]) { return nil, errors.New("Invalid MAC") } paddedOut, err := symcrypt.DecryptCBC(ct[aes.BlockSize:tagStart], ct[:aes.BlockSize], shared[:16]) if err != nil { return } out, err = padding.RemovePadding(paddedOut) return }
func TestCrypt(t *testing.T) { msg := []byte("One ping only, please.") padMsg := padding.AddPadding(msg) key, err := MakeRandom(16) if err != nil { t.Fatalf("%v", err) } iv, err := MakeRandom(16) if err != nil { t.Fatalf("%v", err) } out, err := EncryptCBC(padMsg, iv, key) if err != nil { t.Fatalf("%v", err) } out, err = DecryptCBC(out, iv, key) if err != nil { t.Fatalf("%v", err) } unpadOut, err := padding.RemovePadding(out) if err != nil { t.Fatalf("%v", err) } else if !bytes.Equal(unpadOut, msg) { t.Fatal("Decrypted message doesn't match original plaintext.") } }
// Decrypt decrypts a file using the keys in the key cache. func (c *Cryptor) Decrypt(in []byte, user string) (resp []byte, labels, names []string, secure bool, err error) { // unwrap encrypted file var encrypted EncryptedData if err = json.Unmarshal(in, &encrypted); err != nil { return } if encrypted.Version != DEFAULT_VERSION && encrypted.Version != -1 { return nil, nil, nil, secure, errors.New("Unknown version") } secure = encrypted.Version == -1 hmacKey, err := c.records.GetHMACKey() if err != nil { return } if err = encrypted.unlock(hmacKey); err != nil { return } // make sure file was encrypted with the active vault vaultId, err := c.records.GetVaultID() if err != nil { return } if encrypted.VaultId != vaultId { return nil, nil, nil, secure, errors.New("Wrong vault") } // compute HMAC expectedMAC := encrypted.computeHmac(hmacKey) if !hmac.Equal(encrypted.Signature, expectedMAC) { err = errors.New("Signature mismatch") return } // decrypt file key with delegate keys var unwrappedKey = make([]byte, 16) unwrappedKey, names, err = encrypted.unwrapKey(c.cache, user) if err != nil { return } aesCrypt, err := aes.NewCipher(unwrappedKey) if err != nil { return } clearData := make([]byte, len(encrypted.Data)) aesCBC := cipher.NewCBCDecrypter(aesCrypt, encrypted.IV) // decrypt contents of file aesCBC.CryptBlocks(clearData, encrypted.Data) resp, err = padding.RemovePadding(clearData) labels = encrypted.Labels return }
// Decrypt decrypts a file using the keys in the key cache. func Decrypt(in []byte) (resp []byte, err error) { // unwrap encrypted file var encrypted EncryptedData if err = json.Unmarshal(in, &encrypted); err != nil { return } if encrypted.Version != DEFAULT_VERSION { return nil, errors.New("Unknown version") } // make sure file was encrypted with the active vault vaultId, err := passvault.GetVaultId() if err != nil { return } if encrypted.VaultId != vaultId { return nil, errors.New("Wrong vault") } // validate the size of the keys for _, multiKey := range encrypted.KeySet { if len(multiKey.Key) != 16 { err = errors.New("Invalid Input") return } } // compute HMAC hmacKey, err := passvault.GetHmacKey() if err != nil { return } expectedMAC := computeHmac(hmacKey, encrypted) if !hmac.Equal(encrypted.Signature, expectedMAC) { err = errors.New("Signature mismatch") return } // decrypt file key with delegate keys var unwrappedKey = make([]byte, 16) if unwrappedKey, err = unwrapKey(encrypted.KeySet, encrypted.KeySetRSA); err != nil { return } aesCrypt, err := aes.NewCipher(unwrappedKey) if err != nil { return } clearData := make([]byte, len(encrypted.Data)) aesCBC := cipher.NewCBCDecrypter(aesCrypt, encrypted.IV) // decrypt contents of file aesCBC.CryptBlocks(clearData, encrypted.Data) return padding.RemovePadding(clearData) }