123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- package crypto4go
- import (
- "crypto/aes"
- "crypto/cipher"
- "crypto/md5"
- "crypto/rand"
- "errors"
- "fmt"
- "github.com/smartwalle/crypto4go/pbkdf2"
- "hash"
- "io"
- )
- const (
- kPKCS5SaltLen = 8
- kPKCS5DefaultIter = 2048
- kPKCS5DefaultMagic = "Salted__"
- kEVPMaxIvLen = 16
- )
- func RandBytes(length int) (data []byte, err error) {
- data = make([]byte, length)
- if _, err = io.ReadFull(rand.Reader, data); err != nil {
- return nil, err
- }
- return data, err
- }
- func AESCBCEncryptWithSalt(plaintext, key []byte, iter int, magic string, h func() hash.Hash) ([]byte, error) {
- return AESEncryptWithSalt(plaintext, key, iter, magic, h, AESCBCEncrypt)
- }
- func AESCBCDecryptWithSalt(data, key []byte, iter int, magic string, h func() hash.Hash) ([]byte, error) {
- return AESDecryptWithSalt(data, key, iter, magic, h, AESCBCDecrypt)
- }
- func AESEncryptWithSalt(plaintext, key []byte, iter int, magic string, h func() hash.Hash, f func(plaintext, key, iv []byte) ([]byte, error)) ([]byte, error) {
- if iter <= 0 {
- iter = kPKCS5DefaultIter
- }
- if h == nil {
- h = md5.New
- }
- var salt, _ = RandBytes(kPKCS5SaltLen)
- var sKey = pbkdf2.Key(key, salt, iter, len(key), h)
- var sIV = pbkdf2.Key(sKey, salt, iter, kEVPMaxIvLen, h)
- var ciphertext, err = f(plaintext, sKey, sIV)
- ciphertext = append(salt, ciphertext...)
- ciphertext = append([]byte(magic), ciphertext...)
- return ciphertext, err
- }
- func AESDecryptWithSalt(ciphertext, key []byte, iterCount int, magic string, h func() hash.Hash, f func(ciphertext, key, iv []byte) ([]byte, error)) ([]byte, error) {
- if iterCount <= 0 {
- iterCount = kPKCS5DefaultIter
- }
- if h == nil {
- h = md5.New
- }
- //if len(ciphertext) <= len(magic) + kPKCS5SaltLen {
- // return nil, errors.New("Error")
- //}
- var salt = ciphertext[len(magic) : len(magic)+kPKCS5SaltLen]
- var sKey = pbkdf2.Key(key, salt, iterCount, len(key), h)
- var sIV = pbkdf2.Key(sKey, salt, iterCount, kEVPMaxIvLen, h)
- var plaintext, err = f(ciphertext[len(magic)+kPKCS5SaltLen:], sKey, sIV)
- return plaintext, err
- }
- // AESCBCEncrypt 由key的长度决定是128, 192 还是 256
- func AESCBCEncrypt(plaintext, key, iv []byte) ([]byte, error) {
- var block, err = aes.NewCipher(key)
- if err != nil {
- return nil, err
- }
- var blockSize = block.BlockSize()
- iv = iv[:blockSize]
- var src = PKCS7Padding(plaintext, blockSize)
- var dst = make([]byte, len(src))
- var mode = cipher.NewCBCEncrypter(block, iv)
- mode.CryptBlocks(dst, src)
- return dst, nil
- }
- func AESCBCDecrypt(ciphertext, key, iv []byte) ([]byte, error) {
- var block, err = aes.NewCipher(key)
- if err != nil {
- return nil, err
- }
- var blockSize = block.BlockSize()
- iv = iv[:blockSize]
- var dst = make([]byte, len(ciphertext))
- var mode = cipher.NewCBCDecrypter(block, iv)
- mode.CryptBlocks(dst, ciphertext)
- dst = PKCS7UnPadding(dst)
- return dst, nil
- }
- func AESCFBEncrypt(plaintext, key, iv []byte) ([]byte, error) {
- var block, err = aes.NewCipher(key)
- if err != nil {
- return nil, err
- }
- var blockSize = block.BlockSize()
- iv = iv[:blockSize]
- var dst = make([]byte, len(plaintext))
- var mode = cipher.NewCFBEncrypter(block, iv)
- mode.XORKeyStream(dst, plaintext)
- return dst, nil
- }
- func AESCFBDecrypt(ciphertext, key, iv []byte) ([]byte, error) {
- var block, err = aes.NewCipher(key)
- if err != nil {
- return nil, err
- }
- var blockSize = block.BlockSize()
- iv = iv[:blockSize]
- var dst = make([]byte, len(ciphertext))
- var mode = cipher.NewCFBDecrypter(block, iv)
- mode.XORKeyStream(dst, ciphertext)
- return dst, nil
- }
- func AESGCMEncrypt(plaintext, key []byte) ([]byte, error) {
- var block, err = aes.NewCipher(key)
- if err != nil {
- return nil, err
- }
- mode, err := cipher.NewGCM(block)
- if err != nil {
- return nil, err
- }
- nonce, err := RandBytes(mode.NonceSize())
- if err != nil {
- return nil, err
- }
- return mode.Seal(nonce, nonce, plaintext, nil), nil
- }
- func AESGCMEncryptWithNonce(plaintext, key, nonce []byte) ([]byte, error) {
- var block, err = aes.NewCipher(key)
- if err != nil {
- return nil, err
- }
- mode, err := cipher.NewGCM(block)
- if err != nil {
- return nil, err
- }
- if len(nonce) != mode.NonceSize() {
- return nil, fmt.Errorf("invalid nonce size, must contain %d characters", mode.NonceSize())
- }
- return mode.Seal(nil, nonce, plaintext, nil), nil
- }
- func AESGCMDecrypt(ciphertext, key []byte) ([]byte, error) {
- var block, err = aes.NewCipher(key)
- if err != nil {
- return nil, err
- }
- mode, err := cipher.NewGCM(block)
- if err != nil {
- return nil, err
- }
- nonceSize := mode.NonceSize()
- if len(ciphertext) < nonceSize {
- return nil, errors.New("ciphertext too short")
- }
- var nonce []byte
- nonce, ciphertext = ciphertext[:nonceSize], ciphertext[nonceSize:]
- return mode.Open(nil, nonce, ciphertext, nil)
- }
- func AESGCMDecryptWithNonce(ciphertext, key, nonce []byte) ([]byte, error) {
- var block, err = aes.NewCipher(key)
- if err != nil {
- return nil, err
- }
- mode, err := cipher.NewGCM(block)
- if err != nil {
- return nil, err
- }
- if len(nonce) != mode.NonceSize() {
- return nil, fmt.Errorf("invalid nonce size, must contain %d characters", mode.NonceSize())
- }
- return mode.Open(nil, nonce, ciphertext, nil)
- }
|