@ -76,35 +76,46 @@ import (
"path"
"path"
)
)
const scryptN int = 262144 // 2^18
const (
const scryptr int = 8
// 2^18 / 8 / 1 uses 256MB memory and approx 1s CPU time on a modern CPU.
const scryptp int = 1
scryptN = 1 << 18
const scryptdkLen int = 32
scryptr = 8
scryptp = 1
scryptdkLen = 32
)
type KeyStorePassphrase struct {
type k eyStorePassphrase struct {
keysDirPath string
keysDirPath string
}
}
func ( ks KeyStorePassphrase ) GenerateNewKey ( auth string ) ( key * Key , err error ) {
func NewKeyStorePassphrase ( path string ) KeyStore2 {
key , err = GenerateNewKeyDefault ( ks , auth )
ks := new ( keyStorePassphrase )
return
ks . keysDirPath = path
return ks
}
func ( ks keyStorePassphrase ) GenerateNewKey ( auth string ) ( key * Key , err error ) {
return GenerateNewKeyDefault ( ks , auth )
}
}
func ( ks KeyStorePassphrase ) GetKey ( keyId * uuid . UUID , auth string ) ( key * Key , err error ) {
func ( ks k eyStorePassphrase) GetKey ( keyId * uuid . UUID , auth string ) ( key * Key , err error ) {
keyBytes , flags , err := DecryptKey ( ks , keyId , auth )
keyBytes , flags , err := DecryptKey ( ks , keyId , auth )
if err != nil {
return nil , err
}
key = new ( Key )
key = new ( Key )
key . Id = keyId
key . Id = keyId
copy ( key . Flags [ : ] , flags [ 0 : 4 ] )
copy ( key . Flags [ : ] , flags [ 0 : 4 ] )
key . PrivateKey = ToECDSA ( keyBytes )
key . PrivateKey = ToECDSA ( keyBytes )
return
return key , err
}
}
func ( ks K eyStorePassphrase) StoreKey ( key * Key , auth string ) ( err error ) {
func ( ks k eyStorePassphrase) StoreKey ( key * Key , auth string ) ( err error ) {
authArray := [ ] byte ( auth )
authArray := [ ] byte ( auth )
salt := GetEntropyCSPRNG ( 32 )
salt := GetEntropyCSPRNG ( 32 )
derivedKey , err := scrypt . Key ( authArray , salt , scryptN , scryptr , scryptp , scryptdkLen )
derivedKey , err := scrypt . Key ( authArray , salt , scryptN , scryptr , scryptp , scryptdkLen )
if err != nil {
if err != nil {
return
return err
}
}
keyBytes := FromECDSA ( key . PrivateKey )
keyBytes := FromECDSA ( key . PrivateKey )
@ -113,7 +124,7 @@ func (ks KeyStorePassphrase) StoreKey(key *Key, auth string) (err error) {
AES256Block , err := aes . NewCipher ( derivedKey )
AES256Block , err := aes . NewCipher ( derivedKey )
if err != nil {
if err != nil {
return
return err
}
}
iv := GetEntropyCSPRNG ( aes . BlockSize ) // 16
iv := GetEntropyCSPRNG ( aes . BlockSize ) // 16
@ -126,70 +137,68 @@ func (ks KeyStorePassphrase) StoreKey(key *Key, auth string) (err error) {
hex . EncodeToString ( iv ) ,
hex . EncodeToString ( iv ) ,
hex . EncodeToString ( cipherText ) ,
hex . EncodeToString ( cipherText ) ,
}
}
keyStruct := KeyProtected JSON{
keyStruct := EncryptedKey JSON{
key . Id . String ( ) ,
key . Id . String ( ) ,
hex . EncodeToString ( key . Flags [ : ] ) ,
hex . EncodeToString ( key . Flags [ : ] ) ,
cipherStruct ,
cipherStruct ,
}
}
keyJSON , err := json . Marshal ( keyStruct )
keyJSON , err := json . Marshal ( keyStruct )
if err != nil {
if err != nil {
return
return err
}
}
err = WriteKeyFile ( key . Id . String ( ) , ks . keysDirPath , keyJSON )
return WriteKeyFile ( key . Id . String ( ) , ks . keysDirPath , keyJSON )
return
}
}
func ( ks K eyStorePassphrase) DeleteKey ( keyId * uuid . UUID , auth string ) ( err error ) {
func ( ks k eyStorePassphrase) DeleteKey ( keyId * uuid . UUID , auth string ) ( err error ) {
// only delete if correct passphrase is given
// only delete if correct passphrase is given
_ , _ , err = DecryptKey ( ks , keyId , auth )
_ , _ , err = DecryptKey ( ks , keyId , auth )
if err != nil {
if err != nil {
return
return err
}
}
keyDirPath := path . Join ( ks . keysDirPath , keyId . String ( ) )
keyDirPath := path . Join ( ks . keysDirPath , keyId . String ( ) )
err = os . RemoveAll ( keyDirPath )
return os . RemoveAll ( keyDirPath )
return
}
}
func DecryptKey ( ks K eyStorePassphrase, keyId * uuid . UUID , auth string ) ( keyBytes [ ] byte , flags [ ] byte , err error ) {
func DecryptKey ( ks k eyStorePassphrase, keyId * uuid . UUID , auth string ) ( keyBytes [ ] byte , flags [ ] byte , err error ) {
fileContent , err := GetKeyFile ( ks . keysDirPath , keyId )
fileContent , err := GetKeyFile ( ks . keysDirPath , keyId )
if err != nil {
if err != nil {
return
return nil , nil , err
}
}
keyProtected := new ( KeyProtected JSON)
keyProtected := new ( EncryptedKey JSON)
err = json . Unmarshal ( fileContent , keyProtected )
err = json . Unmarshal ( fileContent , keyProtected )
flags , err = hex . DecodeString ( keyProtected . Flags )
flags , err = hex . DecodeString ( keyProtected . Flags )
if err != nil {
if err != nil {
return
return nil , nil , err
}
}
salt , err := hex . DecodeString ( keyProtected . Crypto . Salt )
salt , err := hex . DecodeString ( keyProtected . Crypto . Salt )
if err != nil {
if err != nil {
return
return nil , nil , err
}
}
iv , err := hex . DecodeString ( keyProtected . Crypto . IV )
iv , err := hex . DecodeString ( keyProtected . Crypto . IV )
if err != nil {
if err != nil {
return
return nil , nil , err
}
}
cipherText , err := hex . DecodeString ( keyProtected . Crypto . CipherText )
cipherText , err := hex . DecodeString ( keyProtected . Crypto . CipherText )
if err != nil {
if err != nil {
return
return nil , nil , err
}
}
authArray := [ ] byte ( auth )
authArray := [ ] byte ( auth )
derivedKey , err := scrypt . Key ( authArray , salt , scryptN , scryptr , scryptp , scryptdkLen )
derivedKey , err := scrypt . Key ( authArray , salt , scryptN , scryptr , scryptp , scryptdkLen )
if err != nil {
if err != nil {
return
return nil , nil , err
}
}
AES256Block , err := aes . NewCipher ( derivedKey )
AES256Block , err := aes . NewCipher ( derivedKey )
if err != nil {
if err != nil {
return
return nil , nil , err
}
}
AES256CBCDecrypter := cipher . NewCBCDecrypter ( AES256Block , iv )
AES256CBCDecrypter := cipher . NewCBCDecrypter ( AES256Block , iv )
@ -199,14 +208,14 @@ func DecryptKey(ks KeyStorePassphrase, keyId *uuid.UUID, auth string) (keyBytes
plainText := PKCS7Unpad ( paddedPlainText )
plainText := PKCS7Unpad ( paddedPlainText )
if plainText == nil {
if plainText == nil {
err = errors . New ( "Decryption failed: PKCS7Unpad failed after decryption" )
err = errors . New ( "Decryption failed: PKCS7Unpad failed after decryption" )
return
return nil , nil , err
}
}
keyBytes = plainText [ : len ( plainText ) - 32 ]
keyBytes = plainText [ : len ( plainText ) - 32 ]
keyBytesHash := plainText [ len ( plainText ) - 32 : ]
keyBytesHash := plainText [ len ( plainText ) - 32 : ]
if ! bytes . Equal ( Sha3 ( keyBytes ) , keyBytesHash ) {
if ! bytes . Equal ( Sha3 ( keyBytes ) , keyBytesHash ) {
err = errors . New ( "Decryption failed: checksum mismatch" )
err = errors . New ( "Decryption failed: checksum mismatch" )
return
return nil , nil , err
}
}
return keyBytes , flags , err
return keyBytes , flags , err
}
}