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) }