You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

51 lines
1.7 KiB

7 years ago
  1. package crypto
  2. import (
  3. "errors"
  4. . "github.com/tendermint/tmlibs/common"
  5. "golang.org/x/crypto/nacl/secretbox"
  6. )
  7. const nonceLen = 24
  8. const secretLen = 32
  9. // secret must be 32 bytes long. Use something like Sha256(Bcrypt(passphrase))
  10. // The ciphertext is (secretbox.Overhead + 24) bytes longer than the plaintext.
  11. // NOTE: call crypto.MixEntropy() first.
  12. func EncryptSymmetric(plaintext []byte, secret []byte) (ciphertext []byte) {
  13. if len(secret) != secretLen {
  14. PanicSanity(Fmt("Secret must be 32 bytes long, got len %v", len(secret)))
  15. }
  16. nonce := CRandBytes(nonceLen)
  17. nonceArr := [nonceLen]byte{}
  18. copy(nonceArr[:], nonce)
  19. secretArr := [secretLen]byte{}
  20. copy(secretArr[:], secret)
  21. ciphertext = make([]byte, nonceLen+secretbox.Overhead+len(plaintext))
  22. copy(ciphertext, nonce)
  23. secretbox.Seal(ciphertext[nonceLen:nonceLen], plaintext, &nonceArr, &secretArr)
  24. return ciphertext
  25. }
  26. // secret must be 32 bytes long. Use something like Sha256(Bcrypt(passphrase))
  27. // The ciphertext is (secretbox.Overhead + 24) bytes longer than the plaintext.
  28. func DecryptSymmetric(ciphertext []byte, secret []byte) (plaintext []byte, err error) {
  29. if len(secret) != secretLen {
  30. PanicSanity(Fmt("Secret must be 32 bytes long, got len %v", len(secret)))
  31. }
  32. if len(ciphertext) <= secretbox.Overhead+nonceLen {
  33. return nil, errors.New("Ciphertext is too short")
  34. }
  35. nonce := ciphertext[:nonceLen]
  36. nonceArr := [nonceLen]byte{}
  37. copy(nonceArr[:], nonce)
  38. secretArr := [secretLen]byte{}
  39. copy(secretArr[:], secret)
  40. plaintext = make([]byte, len(ciphertext)-nonceLen-secretbox.Overhead)
  41. _, ok := secretbox.Open(plaintext[:0], ciphertext[nonceLen:], &nonceArr, &secretArr)
  42. if !ok {
  43. return nil, errors.New("Ciphertext decryption failed")
  44. }
  45. return plaintext, nil
  46. }