You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
412 lines
10 KiB
Go
412 lines
10 KiB
Go
1 year ago
|
package ncrypt
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"crypto/aes"
|
||
|
"crypto/cipher"
|
||
|
"crypto/des"
|
||
|
"crypto/rand"
|
||
|
"errors"
|
||
|
"io"
|
||
|
)
|
||
|
|
||
|
// ErrUnPadding error
|
||
|
var ErrUnPadding = errors.New("un-padding decrypted data fail")
|
||
|
|
||
|
func GenerateAesKey(key []byte, size int) []byte {
|
||
|
genKey := make([]byte, size)
|
||
|
copy(genKey, key)
|
||
|
for i := size; i < len(key); {
|
||
|
for j := 0; j < size && i < len(key); j, i = j+1, i+1 {
|
||
|
genKey[j] ^= key[i]
|
||
|
}
|
||
|
}
|
||
|
return genKey
|
||
|
}
|
||
|
|
||
|
func GenerateDesKey(key []byte) []byte {
|
||
|
genKey := make([]byte, 8)
|
||
|
copy(genKey, key)
|
||
|
for i := 8; i < len(key); {
|
||
|
for j := 0; j < 8 && i < len(key); j, i = j+1, i+1 {
|
||
|
genKey[j] ^= key[i]
|
||
|
}
|
||
|
}
|
||
|
return genKey
|
||
|
}
|
||
|
|
||
|
// PKCS5Padding input data
|
||
|
func PKCS5Padding(src []byte, blockSize int) []byte {
|
||
|
padding := blockSize - len(src)%blockSize
|
||
|
padText := bytes.Repeat([]byte{byte(padding)}, padding)
|
||
|
return append(src, padText...)
|
||
|
}
|
||
|
|
||
|
// PKCS5UnPadding input data
|
||
|
func PKCS5UnPadding(src []byte) ([]byte, error) {
|
||
|
length := len(src)
|
||
|
delLen := int(src[length-1])
|
||
|
|
||
|
if delLen > length {
|
||
|
return nil, ErrUnPadding
|
||
|
}
|
||
|
|
||
|
// fix: 检查删除的填充是否是一样的字符,不一样说明 delLen 值是有问题的,无法解码
|
||
|
if delLen > 1 && src[length-1] != src[length-2] {
|
||
|
return nil, ErrUnPadding
|
||
|
}
|
||
|
|
||
|
return src[:length-delLen], nil
|
||
|
}
|
||
|
|
||
|
// PKCS7Padding input data
|
||
|
func PKCS7Padding(src []byte, blockSize int) []byte {
|
||
|
return PKCS5Padding(src, blockSize)
|
||
|
}
|
||
|
|
||
|
// PKCS7UnPadding input data
|
||
|
func PKCS7UnPadding(src []byte) ([]byte, error) {
|
||
|
return PKCS5UnPadding(src)
|
||
|
}
|
||
|
|
||
|
// AesEcbEncrypt encrypt data with key use AES ECB algorithm
|
||
|
// len(key) should be 16, 24 or 32.
|
||
|
func AesEcbEncrypt(data, key []byte) []byte {
|
||
|
size := len(key)
|
||
|
if size != 16 && size != 24 && size != 32 {
|
||
|
panic("key length shoud be 16 or 24 or 32")
|
||
|
}
|
||
|
|
||
|
length := (len(data) + aes.BlockSize) / aes.BlockSize
|
||
|
plain := make([]byte, length*aes.BlockSize)
|
||
|
|
||
|
copy(plain, data)
|
||
|
|
||
|
pad := byte(len(plain) - len(data))
|
||
|
for i := len(data); i < len(plain); i++ {
|
||
|
plain[i] = pad
|
||
|
}
|
||
|
|
||
|
encrypted := make([]byte, len(plain))
|
||
|
cipher, _ := aes.NewCipher(GenerateAesKey(key, size))
|
||
|
|
||
|
for bs, be := 0, cipher.BlockSize(); bs <= len(data); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||
|
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
|
||
|
}
|
||
|
|
||
|
return encrypted
|
||
|
}
|
||
|
|
||
|
// AesEcbDecrypt decrypt data with key use AES ECB algorithm
|
||
|
// len(key) should be 16, 24 or 32.
|
||
|
func AesEcbDecrypt(encrypted, key []byte) []byte {
|
||
|
size := len(key)
|
||
|
if size != 16 && size != 24 && size != 32 {
|
||
|
panic("key length should be 16 or 24 or 32")
|
||
|
}
|
||
|
cipher, _ := aes.NewCipher(GenerateAesKey(key, size))
|
||
|
decrypted := make([]byte, len(encrypted))
|
||
|
|
||
|
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||
|
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
|
||
|
}
|
||
|
|
||
|
trim := 0
|
||
|
if len(decrypted) > 0 {
|
||
|
trim = len(decrypted) - int(decrypted[len(decrypted)-1])
|
||
|
}
|
||
|
|
||
|
return decrypted[:trim]
|
||
|
}
|
||
|
|
||
|
// AesCbcEncrypt encrypt data with key use AES CBC algorithm
|
||
|
// len(key) should be 16, 24 or 32.
|
||
|
func AesCbcEncrypt(data, key []byte) []byte {
|
||
|
block, _ := aes.NewCipher(key)
|
||
|
data = PKCS7Padding(data, block.BlockSize())
|
||
|
|
||
|
encrypted := make([]byte, aes.BlockSize+len(data))
|
||
|
iv := encrypted[:aes.BlockSize]
|
||
|
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
mode := cipher.NewCBCEncrypter(block, iv)
|
||
|
mode.CryptBlocks(encrypted[aes.BlockSize:], data)
|
||
|
|
||
|
return encrypted
|
||
|
}
|
||
|
|
||
|
// AesCbcDecrypt decrypt data with key use AES CBC algorithm
|
||
|
// len(key) should be 16, 24 or 32.
|
||
|
func AesCbcDecrypt(encrypted, key []byte) ([]byte, error) {
|
||
|
block, _ := aes.NewCipher(key)
|
||
|
|
||
|
iv := encrypted[:aes.BlockSize]
|
||
|
encrypted = encrypted[aes.BlockSize:]
|
||
|
|
||
|
mode := cipher.NewCBCDecrypter(block, iv)
|
||
|
mode.CryptBlocks(encrypted, encrypted)
|
||
|
|
||
|
return PKCS7UnPadding(encrypted)
|
||
|
}
|
||
|
|
||
|
// AesCtrCrypt encrypt data with key use AES CTR algorithm
|
||
|
// len(key) should be 16, 24 or 32.
|
||
|
func AesCtrCrypt(data, key []byte) []byte {
|
||
|
block, _ := aes.NewCipher(key)
|
||
|
|
||
|
iv := bytes.Repeat([]byte("1"), block.BlockSize())
|
||
|
stream := cipher.NewCTR(block, iv)
|
||
|
|
||
|
dst := make([]byte, len(data))
|
||
|
stream.XORKeyStream(dst, data)
|
||
|
|
||
|
return dst
|
||
|
}
|
||
|
|
||
|
// AesCfbEncrypt encrypt data with key use AES CFB algorithm
|
||
|
// len(key) should be 16, 24 or 32.
|
||
|
func AesCfbEncrypt(data, key []byte) []byte {
|
||
|
block, err := aes.NewCipher(key)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
encrypted := make([]byte, aes.BlockSize+len(data))
|
||
|
iv := encrypted[:aes.BlockSize]
|
||
|
|
||
|
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
stream := cipher.NewCFBEncrypter(block, iv)
|
||
|
stream.XORKeyStream(encrypted[aes.BlockSize:], data)
|
||
|
|
||
|
return encrypted
|
||
|
}
|
||
|
|
||
|
// AesCfbDecrypt decrypt data with key use AES CFB algorithm
|
||
|
// len(encrypted) should be greater than 16, len(key) should be 16, 24 or 32.
|
||
|
func AesCfbDecrypt(encrypted, key []byte) []byte {
|
||
|
if len(encrypted) < aes.BlockSize {
|
||
|
panic("encrypted data is too short")
|
||
|
}
|
||
|
|
||
|
block, _ := aes.NewCipher(key)
|
||
|
iv := encrypted[:aes.BlockSize]
|
||
|
encrypted = encrypted[aes.BlockSize:]
|
||
|
|
||
|
stream := cipher.NewCFBDecrypter(block, iv)
|
||
|
|
||
|
stream.XORKeyStream(encrypted, encrypted)
|
||
|
|
||
|
return encrypted
|
||
|
}
|
||
|
|
||
|
// AesOfbEncrypt encrypt data with key use AES OFB algorithm
|
||
|
// len(key) should be 16, 24 or 32.
|
||
|
func AesOfbEncrypt(data, key []byte) []byte {
|
||
|
block, err := aes.NewCipher(key)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
data = PKCS7Padding(data, aes.BlockSize)
|
||
|
encrypted := make([]byte, aes.BlockSize+len(data))
|
||
|
iv := encrypted[:aes.BlockSize]
|
||
|
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
stream := cipher.NewOFB(block, iv)
|
||
|
stream.XORKeyStream(encrypted[aes.BlockSize:], data)
|
||
|
|
||
|
return encrypted
|
||
|
}
|
||
|
|
||
|
// AesOfbDecrypt decrypt data with key use AES OFB algorithm
|
||
|
// len(key) should be 16, 24 or 32.
|
||
|
func AesOfbDecrypt(data, key []byte) ([]byte, error) {
|
||
|
block, err := aes.NewCipher(key)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
iv := data[:aes.BlockSize]
|
||
|
data = data[aes.BlockSize:]
|
||
|
if len(data)%aes.BlockSize != 0 {
|
||
|
return nil, errors.New("data must % 16")
|
||
|
}
|
||
|
|
||
|
decrypted := make([]byte, len(data))
|
||
|
mode := cipher.NewOFB(block, iv)
|
||
|
mode.XORKeyStream(decrypted, data)
|
||
|
|
||
|
return PKCS7UnPadding(decrypted)
|
||
|
}
|
||
|
|
||
|
// DesEcbEncrypt encrypt data with key use DES ECB algorithm
|
||
|
// len(key) should be 8.
|
||
|
func DesEcbEncrypt(data, key []byte) []byte {
|
||
|
length := (len(data) + des.BlockSize) / des.BlockSize
|
||
|
plain := make([]byte, length*des.BlockSize)
|
||
|
copy(plain, data)
|
||
|
|
||
|
pad := byte(len(plain) - len(data))
|
||
|
for i := len(data); i < len(plain); i++ {
|
||
|
plain[i] = pad
|
||
|
}
|
||
|
|
||
|
encrypted := make([]byte, len(plain))
|
||
|
cipher, _ := des.NewCipher(GenerateDesKey(key))
|
||
|
|
||
|
for bs, be := 0, cipher.BlockSize(); bs <= len(data); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||
|
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
|
||
|
}
|
||
|
|
||
|
return encrypted
|
||
|
}
|
||
|
|
||
|
// DesEcbDecrypt decrypt data with key use DES ECB algorithm
|
||
|
// len(key) should be 8.
|
||
|
func DesEcbDecrypt(encrypted, key []byte) []byte {
|
||
|
cipher, _ := des.NewCipher(GenerateDesKey(key))
|
||
|
decrypted := make([]byte, len(encrypted))
|
||
|
|
||
|
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||
|
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
|
||
|
}
|
||
|
|
||
|
trim := 0
|
||
|
if len(decrypted) > 0 {
|
||
|
trim = len(decrypted) - int(decrypted[len(decrypted)-1])
|
||
|
}
|
||
|
|
||
|
return decrypted[:trim]
|
||
|
}
|
||
|
|
||
|
// DesCbcEncrypt encrypt data with key use DES CBC algorithm
|
||
|
// len(key) should be 8.
|
||
|
func DesCbcEncrypt(data, key []byte) []byte {
|
||
|
block, _ := des.NewCipher(key)
|
||
|
data = PKCS7Padding(data, block.BlockSize())
|
||
|
|
||
|
encrypted := make([]byte, des.BlockSize+len(data))
|
||
|
iv := encrypted[:des.BlockSize]
|
||
|
|
||
|
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
mode := cipher.NewCBCEncrypter(block, iv)
|
||
|
mode.CryptBlocks(encrypted[des.BlockSize:], data)
|
||
|
|
||
|
return encrypted
|
||
|
}
|
||
|
|
||
|
// DesCbcDecrypt decrypt data with key use DES CBC algorithm
|
||
|
// len(key) should be 8.
|
||
|
func DesCbcDecrypt(encrypted, key []byte) ([]byte, error) {
|
||
|
block, _ := des.NewCipher(key)
|
||
|
|
||
|
iv := encrypted[:des.BlockSize]
|
||
|
encrypted = encrypted[des.BlockSize:]
|
||
|
|
||
|
mode := cipher.NewCBCDecrypter(block, iv)
|
||
|
mode.CryptBlocks(encrypted, encrypted)
|
||
|
|
||
|
return PKCS7UnPadding(encrypted)
|
||
|
}
|
||
|
|
||
|
// DesCtrCrypt encrypt data with key use DES CTR algorithm
|
||
|
// len(key) should be 8.
|
||
|
func DesCtrCrypt(data, key []byte) []byte {
|
||
|
block, _ := des.NewCipher(key)
|
||
|
|
||
|
iv := bytes.Repeat([]byte("1"), block.BlockSize())
|
||
|
stream := cipher.NewCTR(block, iv)
|
||
|
|
||
|
dst := make([]byte, len(data))
|
||
|
stream.XORKeyStream(dst, data)
|
||
|
|
||
|
return dst
|
||
|
}
|
||
|
|
||
|
// DesCfbEncrypt encrypt data with key use DES CFB algorithm
|
||
|
// len(key) should be 8.
|
||
|
func DesCfbEncrypt(data, key []byte) []byte {
|
||
|
block, err := des.NewCipher(key)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
encrypted := make([]byte, des.BlockSize+len(data))
|
||
|
iv := encrypted[:des.BlockSize]
|
||
|
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
stream := cipher.NewCFBEncrypter(block, iv)
|
||
|
stream.XORKeyStream(encrypted[des.BlockSize:], data)
|
||
|
|
||
|
return encrypted
|
||
|
}
|
||
|
|
||
|
// DesCfbDecrypt decrypt data with key use DES CFB algorithm
|
||
|
// len(encrypted) should be greater than 16, len(key) should be 8.
|
||
|
func DesCfbDecrypt(encrypted, key []byte) []byte {
|
||
|
block, _ := des.NewCipher(key)
|
||
|
if len(encrypted) < des.BlockSize {
|
||
|
panic("encrypted data is too short")
|
||
|
}
|
||
|
iv := encrypted[:des.BlockSize]
|
||
|
encrypted = encrypted[des.BlockSize:]
|
||
|
|
||
|
stream := cipher.NewCFBDecrypter(block, iv)
|
||
|
stream.XORKeyStream(encrypted, encrypted)
|
||
|
|
||
|
return encrypted
|
||
|
}
|
||
|
|
||
|
// DesOfbEncrypt encrypt data with key use DES OFB algorithm
|
||
|
// len(key) should be 16, 24 or 32.
|
||
|
func DesOfbEncrypt(data, key []byte) []byte {
|
||
|
block, err := des.NewCipher(key)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
data = PKCS7Padding(data, des.BlockSize)
|
||
|
encrypted := make([]byte, des.BlockSize+len(data))
|
||
|
iv := encrypted[:des.BlockSize]
|
||
|
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
stream := cipher.NewOFB(block, iv)
|
||
|
stream.XORKeyStream(encrypted[des.BlockSize:], data)
|
||
|
|
||
|
return encrypted
|
||
|
}
|
||
|
|
||
|
// DesOfbDecrypt decrypt data with key use DES OFB algorithm
|
||
|
// len(key) should be 8.
|
||
|
func DesOfbDecrypt(data, key []byte) ([]byte, error) {
|
||
|
block, err := des.NewCipher(key)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
iv := data[:des.BlockSize]
|
||
|
data = data[des.BlockSize:]
|
||
|
if len(data)%des.BlockSize != 0 {
|
||
|
return nil, errors.New("data must % 16")
|
||
|
}
|
||
|
|
||
|
decrypted := make([]byte, len(data))
|
||
|
mode := cipher.NewOFB(block, iv)
|
||
|
mode.XORKeyStream(decrypted, data)
|
||
|
|
||
|
return PKCS7UnPadding(decrypted)
|
||
|
}
|