github.com/vipernet-xyz/tm@v0.34.24/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/vipernet-xyz/tm/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  }