github.com/DFWallet/tendermint-cosmos@v0.0.2/crypto/xsalsa20symmetric/symmetric.go (about) 1 package xsalsa20symmetric 2 3 import ( 4 "errors" 5 "fmt" 6 7 "golang.org/x/crypto/nacl/secretbox" 8 9 "github.com/DFWallet/tendermint-cosmos/crypto" 10 ) 11 12 // TODO, make this into a struct that implements crypto.Symmetric. 13 14 const nonceLen = 24 15 const secretLen = 32 16 17 // secret must be 32 bytes long. Use something like Sha256(Bcrypt(passphrase)) 18 // The ciphertext is (secretbox.Overhead + 24) bytes longer than the plaintext. 19 func EncryptSymmetric(plaintext []byte, secret []byte) (ciphertext []byte) { 20 if len(secret) != secretLen { 21 panic(fmt.Sprintf("Secret must be 32 bytes long, got len %v", len(secret))) 22 } 23 nonce := crypto.CRandBytes(nonceLen) 24 nonceArr := [nonceLen]byte{} 25 copy(nonceArr[:], nonce) 26 secretArr := [secretLen]byte{} 27 copy(secretArr[:], secret) 28 ciphertext = make([]byte, nonceLen+secretbox.Overhead+len(plaintext)) 29 copy(ciphertext, nonce) 30 secretbox.Seal(ciphertext[nonceLen:nonceLen], plaintext, &nonceArr, &secretArr) 31 return ciphertext 32 } 33 34 // secret must be 32 bytes long. Use something like Sha256(Bcrypt(passphrase)) 35 // The ciphertext is (secretbox.Overhead + 24) bytes longer than the plaintext. 36 func DecryptSymmetric(ciphertext []byte, secret []byte) (plaintext []byte, err error) { 37 if len(secret) != secretLen { 38 panic(fmt.Sprintf("Secret must be 32 bytes long, got len %v", len(secret))) 39 } 40 if len(ciphertext) <= secretbox.Overhead+nonceLen { 41 return nil, errors.New("ciphertext is too short") 42 } 43 nonce := ciphertext[:nonceLen] 44 nonceArr := [nonceLen]byte{} 45 copy(nonceArr[:], nonce) 46 secretArr := [secretLen]byte{} 47 copy(secretArr[:], secret) 48 plaintext = make([]byte, len(ciphertext)-nonceLen-secretbox.Overhead) 49 _, ok := secretbox.Open(plaintext[:0], ciphertext[nonceLen:], &nonceArr, &secretArr) 50 if !ok { 51 return nil, errors.New("ciphertext decryption failed") 52 } 53 return plaintext, nil 54 }