diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml index 47b1488..7dd0e95 100644 --- a/.github/workflows/analysis.yml +++ b/.github/workflows/analysis.yml @@ -13,10 +13,10 @@ name: "analysis" on: push: - branches: [ main ] + branches: [ develop ] pull_request: # The branches below must be a subset of the branches above - branches: [ main ] + branches: [ develop ] schedule: - cron: '18 19 * * 6' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9b2dcec..8ca3cfd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,9 +2,9 @@ name: test on: push: - branches: [ main ] + branches: [ develop ] pull_request: - branches: [ main ] + branches: [ develop ] jobs: diff --git a/3des.go b/3des.go index 1aa2c31..5eb1b15 100644 --- a/3des.go +++ b/3des.go @@ -6,7 +6,7 @@ import ( // By3Des encrypts by 3des. // 通过 3des 加密 -func (e encrypter) By3Des(c *Cipher) encrypter { +func (e Encrypter) By3Des(c *Cipher) Encrypter { block, err := des.NewTripleDESCipher(c.key) if err != nil { e.Error = invalid3DesKeyError() @@ -26,7 +26,7 @@ func (e encrypter) By3Des(c *Cipher) encrypter { // By3Des decrypts by 3des. // 通过 3des 解密 -func (d decrypter) By3Des(c *Cipher) decrypter { +func (d Decrypter) By3Des(c *Cipher) Decrypter { if d.Error != nil { return d } diff --git a/3des_test.go b/3des_test.go index 212fa7d..38d9550 100644 --- a/3des_test.go +++ b/3des_test.go @@ -16,38 +16,47 @@ var tripleDesTests = []struct { padding cipherPadding input string toHex string - toBase32 string toBase64 string }{ - {CBC, "", "", "", "", ""}, - {CBC, No, "hello world, go!", "7e9194cc827a325d49111eaa503110fe", "P2IZJTECPIZF2SIRD2VFAMIQ7Y======", "fpGUzIJ6Ml1JER6qUDEQ/g=="}, - {CBC, Zero, "hello world", "7e9194cc827a325ddaee992a89c5cd8d", "P2IZJTECPIZF3WXOTEVITRONRU======", "fpGUzIJ6Ml3a7pkqicXNjQ=="}, - {CBC, PKCS5, "hello world", "7e9194cc827a325db9c765859716cc97", "P2IZJTECPIZF3OOHMWCZOFWMS4======", "fpGUzIJ6Ml25x2WFlxbMlw=="}, - {CBC, PKCS7, "hello world", "7e9194cc827a325db9c765859716cc97", "P2IZJTECPIZF3OOHMWCZOFWMS4======", "fpGUzIJ6Ml25x2WFlxbMlw=="}, - - {CFB, PKCS5, "", "", "", ""}, - {CFB, No, "hello world, go!", "f52dc896ceff0ecc9393c19d4e1e7591", "6UW4RFWO74HMZE4TYGOU4HTVSE======", "9S3Ils7/DsyTk8GdTh51kQ=="}, - {CFB, Zero, "hello world", "f52dc896ceff0ecc9393c1b16e791ab0", "6UW4RFWO74HMZE4TYGYW46I2WA======", "9S3Ils7/DsyTk8GxbnkasA=="}, - {CFB, PKCS5, "hello world", "f52dc896ceff0ecc9393c1b46b7c1fb5", "6UW4RFWO74HMZE4TYG2GW7A7WU======", "9S3Ils7/DsyTk8G0a3wftQ=="}, - {CFB, PKCS7, "hello world", "f52dc896ceff0ecc9393c1b46b7c1fb5", "6UW4RFWO74HMZE4TYG2GW7A7WU======", "9S3Ils7/DsyTk8G0a3wftQ=="}, - - {OFB, PKCS7, "", "", "", ""}, - {OFB, No, "hello world, go!", "f52dc896ceff0eccf869cb59735c3766", "6UW4RFWO74HMZ6DJZNMXGXBXMY======", "9S3Ils7/Dsz4actZc1w3Zg=="}, - {OFB, Zero, "hello world", "f52dc896ceff0eccf869cb75533b5847", "6UW4RFWO74HMZ6DJZN2VGO2YI4======", "9S3Ils7/Dsz4act1UztYRw=="}, - {OFB, PKCS5, "hello world", "f52dc896ceff0eccf869cb70563e5d42", "6UW4RFWO74HMZ6DJZNYFMPS5II======", "9S3Ils7/Dsz4actwVj5dQg=="}, - {OFB, PKCS7, "hello world", "f52dc896ceff0eccf869cb70563e5d42", "6UW4RFWO74HMZ6DJZNYFMPS5II======", "9S3Ils7/Dsz4actwVj5dQg=="}, - - {CTR, PKCS5, "", "", "", ""}, - {CTR, No, "hello world, go!", "f52dc896ceff0ecc366b2281038f6f7f", "6UW4RFWO74HMYNTLEKAQHD3PP4======", "9S3Ils7/Dsw2ayKBA49vfw=="}, - {CTR, Zero, "hello world", "f52dc896ceff0ecc366b22ad23e8005e", "6UW4RFWO74HMYNTLEKWSH2AALY======", "9S3Ils7/Dsw2ayKtI+gAXg=="}, - {CTR, PKCS5, "hello world", "f52dc896ceff0ecc366b22a826ed055b", "6UW4RFWO74HMYNTLEKUCN3IFLM======", "9S3Ils7/Dsw2ayKoJu0FWw=="}, - {CTR, PKCS7, "hello world", "f52dc896ceff0ecc366b22a826ed055b", "6UW4RFWO74HMYNTLEKUCN3IFLM======", "9S3Ils7/Dsw2ayKoJu0FWw=="}, - - {ECB, PKCS7, "", "", "", ""}, - {ECB, No, "hello world, go!", "b8097975c76319c623be7c7aa6e0f3fc", "XAEXS5OHMMM4MI56PR5KNYHT7Q======", "uAl5dcdjGcYjvnx6puDz/A=="}, - {ECB, Zero, "hello world", "b8097975c76319c61971a986e579cdf9", "XAEXS5OHMMM4MGLRVGDOK6ON7E======", "uAl5dcdjGcYZcamG5XnN+Q=="}, - {ECB, PKCS5, "hello world", "b8097975c76319c6172687e0d90fd4d1", "XAEXS5OHMMM4MFZGQ7QNSD6U2E======", "uAl5dcdjGcYXJofg2Q/U0Q=="}, - {ECB, PKCS7, "hello world", "b8097975c76319c6172687e0d90fd4d1", "XAEXS5OHMMM4MFZGQ7QNSD6U2E======", "uAl5dcdjGcYXJofg2Q/U0Q=="}, + {CBC, PKCS7, "", "", ""}, + {CBC, No, "hello world, go!", "7e9194cc827a325d49111eaa503110fe", "fpGUzIJ6Ml1JER6qUDEQ/g=="}, + {CBC, Zero, "hello world", "7e9194cc827a325ddaee992a89c5cd8d", "fpGUzIJ6Ml3a7pkqicXNjQ=="}, + {CBC, PKCS5, "hello world", "7e9194cc827a325db9c765859716cc97", "fpGUzIJ6Ml25x2WFlxbMlw=="}, + {CBC, PKCS7, "hello world", "7e9194cc827a325db9c765859716cc97", "fpGUzIJ6Ml25x2WFlxbMlw=="}, + {CBC, AnsiX923, "hello world", "7e9194cc827a325d2793bb48a7971825", "fpGUzIJ6Ml0nk7tIp5cYJQ=="}, + {CBC, ISO97971, "hello world", "7e9194cc827a325d89d4f50218d6e511", "fpGUzIJ6Ml2J1PUCGNblEQ=="}, + + {CFB, PKCS7, "", "", ""}, + {CFB, No, "hello world, go!", "f52dc896ceff0ecc9393c19d4e1e7591", "9S3Ils7/DsyTk8GdTh51kQ=="}, + {CFB, Zero, "hello world", "f52dc896ceff0ecc9393c1b16e791ab0", "9S3Ils7/DsyTk8GxbnkasA=="}, + {CFB, PKCS5, "hello world", "f52dc896ceff0ecc9393c1b46b7c1fb5", "9S3Ils7/DsyTk8G0a3wftQ=="}, + {CFB, PKCS7, "hello world", "f52dc896ceff0ecc9393c1b46b7c1fb5", "9S3Ils7/DsyTk8G0a3wftQ=="}, + {CFB, AnsiX923, "hello world", "f52dc896ceff0ecc9393c1b16e791ab5", "9S3Ils7/DsyTk8GxbnkatQ=="}, + {CFB, ISO97971, "hello world", "f52dc896ceff0ecc9393c1316e791ab0", "9S3Ils7/DsyTk8ExbnkasA=="}, + + {OFB, PKCS7, "", "", ""}, + {OFB, No, "hello world, go!", "f52dc896ceff0eccf869cb59735c3766", "9S3Ils7/Dsz4actZc1w3Zg=="}, + {OFB, Zero, "hello world", "f52dc896ceff0eccf869cb75533b5847", "9S3Ils7/Dsz4act1UztYRw=="}, + {OFB, PKCS5, "hello world", "f52dc896ceff0eccf869cb70563e5d42", "9S3Ils7/Dsz4actwVj5dQg=="}, + {OFB, PKCS7, "hello world", "f52dc896ceff0eccf869cb70563e5d42", "9S3Ils7/Dsz4actwVj5dQg=="}, + {OFB, AnsiX923, "hello world", "f52dc896ceff0eccf869cb75533b5842", "9S3Ils7/Dsz4act1UztYQg=="}, + {OFB, ISO97971, "hello world", "f52dc896ceff0eccf869cbf5533b5847", "9S3Ils7/Dsz4acv1UztYRw=="}, + + {CTR, PKCS7, "", "", ""}, + {CTR, No, "hello world, go!", "f52dc896ceff0ecc366b2281038f6f7f", "9S3Ils7/Dsw2ayKBA49vfw=="}, + {CTR, Zero, "hello world", "f52dc896ceff0ecc366b22ad23e8005e", "9S3Ils7/Dsw2ayKtI+gAXg=="}, + {CTR, PKCS5, "hello world", "f52dc896ceff0ecc366b22a826ed055b", "9S3Ils7/Dsw2ayKoJu0FWw=="}, + {CTR, PKCS7, "hello world", "f52dc896ceff0ecc366b22a826ed055b", "9S3Ils7/Dsw2ayKoJu0FWw=="}, + {CTR, AnsiX923, "hello world", "f52dc896ceff0ecc366b22ad23e8005b", "9S3Ils7/Dsw2ayKtI+gAWw=="}, + {CTR, ISO97971, "hello world", "f52dc896ceff0ecc366b222d23e8005e", "9S3Ils7/Dsw2ayItI+gAXg=="}, + + {ECB, PKCS7, "", "", ""}, + {ECB, No, "hello world, go!", "b8097975c76319c623be7c7aa6e0f3fc", "uAl5dcdjGcYjvnx6puDz/A=="}, + {ECB, Zero, "hello world", "b8097975c76319c61971a986e579cdf9", "uAl5dcdjGcYZcamG5XnN+Q=="}, + {ECB, PKCS5, "hello world", "b8097975c76319c6172687e0d90fd4d1", "uAl5dcdjGcYXJofg2Q/U0Q=="}, + {ECB, PKCS7, "hello world", "b8097975c76319c6172687e0d90fd4d1", "uAl5dcdjGcYXJofg2Q/U0Q=="}, + {ECB, AnsiX923, "hello world", "b8097975c76319c6d98a83ce5ec18698", "uAl5dcdjGcbZioPOXsGGmA=="}, + {ECB, ISO97971, "hello world", "b8097975c76319c66b1c75b91028ca62", "uAl5dcdjGcZrHHW5ECjKYg=="}, } func Test3Des_Encrypt_String(t *testing.T) { @@ -55,15 +64,15 @@ func Test3Des_Encrypt_String(t *testing.T) { raw := Decode.FromString(test.toHex).ByHex().ToString() e := Encrypt.FromString(test.input).By3Des(getCipher(test.mode, test.padding, tripleDesKey, tripleDesIV)) - t.Run(fmt.Sprintf(string(test.mode)+"_raw_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_raw_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, raw, e.ToRawString()) }) - t.Run(fmt.Sprintf(string(test.mode)+"_hex_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_hex_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, test.toHex, e.ToHexString()) }) - t.Run(fmt.Sprintf(string(test.mode)+"_base64_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_base64_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, test.toBase64, e.ToBase64String()) }) @@ -75,7 +84,7 @@ func Test3Des_Decrypt_String(t *testing.T) { raw := Decode.FromString(test.toHex).ByHex().ToString() e := Decrypt.FromRawString(raw).By3Des(getCipher(test.mode, test.padding, tripleDesKey, tripleDesIV)) - t.Run(fmt.Sprintf(string(test.mode)+"_raw_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_raw_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, test.input, e.ToString()) assert.Equal(t, test.input, fmt.Sprintf("%s", e)) @@ -85,7 +94,7 @@ func Test3Des_Decrypt_String(t *testing.T) { for index, test := range tripleDesTests { e := Decrypt.FromHexString(test.toHex).By3Des(getCipher(test.mode, test.padding, tripleDesKey, tripleDesIV)) - t.Run(fmt.Sprintf(string(test.mode)+"_hex_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_hex_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, test.input, e.ToString()) assert.Equal(t, test.input, fmt.Sprintf("%s", e)) @@ -95,7 +104,7 @@ func Test3Des_Decrypt_String(t *testing.T) { for index, test := range tripleDesTests { e := Decrypt.FromBase64String(test.toBase64).By3Des(getCipher(test.mode, test.padding, tripleDesKey, tripleDesIV)) - t.Run(fmt.Sprintf(string(test.mode)+"_base64_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_base64_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, test.input, e.ToString()) assert.Equal(t, test.input, fmt.Sprintf("%s", e)) @@ -108,15 +117,15 @@ func Test3Des_Encrypt_Bytes(t *testing.T) { raw := Decode.FromBytes([]byte(test.toHex)).ByHex().ToBytes() e := Encrypt.FromBytes([]byte(test.input)).By3Des(getCipher(test.mode, test.padding, []byte(tripleDesKey), []byte(tripleDesIV))) - t.Run(fmt.Sprintf(string(test.mode)+"_raw_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_raw_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, raw, e.ToRawBytes()) }) - t.Run(fmt.Sprintf(string(test.mode)+"_hex_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_hex_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, []byte(test.toHex), e.ToHexBytes()) }) - t.Run(fmt.Sprintf(string(test.mode)+"_base64_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_base64_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, []byte(test.toBase64), e.ToBase64Bytes()) }) @@ -128,7 +137,7 @@ func Test3Des_Decrypt_Bytes(t *testing.T) { raw := Decode.FromBytes([]byte(test.toHex)).ByHex().ToBytes() e := Decrypt.FromRawBytes(raw).By3Des(getCipher(test.mode, test.padding, []byte(tripleDesKey), []byte(tripleDesIV))) - t.Run(fmt.Sprintf(string(test.mode)+"_raw_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_raw_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, []byte(test.input), e.ToBytes()) }) @@ -137,7 +146,7 @@ func Test3Des_Decrypt_Bytes(t *testing.T) { for index, test := range tripleDesTests { e := Decrypt.FromHexBytes([]byte(test.toHex)).By3Des(getCipher(test.mode, test.padding, []byte(tripleDesKey), []byte(tripleDesIV))) - t.Run(fmt.Sprintf(string(test.mode)+"_hex_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_hex_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, []byte(test.input), e.ToBytes()) }) @@ -146,7 +155,7 @@ func Test3Des_Decrypt_Bytes(t *testing.T) { for index, test := range tripleDesTests { e := Decrypt.FromBase64Bytes([]byte(test.toBase64)).By3Des(getCipher(test.mode, test.padding, []byte(tripleDesKey), []byte(tripleDesIV))) - t.Run(fmt.Sprintf(string(test.mode)+"_base64_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_base64_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, []byte(test.input), e.ToBytes()) }) diff --git a/README.cn.md b/README.cn.md index a6cb28d..86d343e 100755 --- a/README.cn.md +++ b/README.cn.md @@ -1,4 +1,5 @@ # dongle # + [![Carbon Release](https://img.shields.io/github/release/golang-module/dongle.svg)](https://github.com/golang-module/dongle/releases) [![Go Build](https://github.com/golang-module/dongle/actions/workflows/test.yml/badge.svg)](https://github.com/golang-module/dongle/actions) [![Go Report Card](https://goreportcard.com/badge/github.com/golang-module/dongle)](https://goreportcard.com/report/github.com/golang-module/dongle) @@ -8,7 +9,7 @@ 简体中文 | [English](README.md) -一个轻量级、语义化、对开发者友好的 golang 编码解码、加密解密库 +一个轻量级、语义化、对开发者友好的 golang 编码解码、加密解密和签名验签库 `Dongle` 已被 [awesome-go](https://github.com/avelino/awesome-go#security "awesome-go") 收录, 如果您觉得不错,请给个 star 吧 @@ -17,6 +18,7 @@ [gitee.com/golang-module/dongle](https://gitee.com/golang-module/dongle "gitee.com/golang-module/dongle") ### 安装使用 + ```go // 使用 github 库 go get -u github.com/golang-module/dongle @@ -34,9 +36,11 @@ import ( ``` ### 用法示例 + #### 编码&解码 ##### Hex 编码、解码 + ```go // 对字符串进行 hex 编码,输出字符串 dongle.Encode.FromString("hello world").ByHex().ToString() // 68656c6c6f20776f726c64 @@ -120,6 +124,7 @@ dongle.Decode.FromBytes([]byte("aGVsbG8gd29ybGQ=")).ByBase64().ToBytes() // []by ``` ##### Base64URL 编码、解码 + ```go // 对 url 字符进行 base64 编码,输出字符串 dongle.Encode.FromString("www.gouguoyin.cn").ByBase64URL().ToString() // d3d3LmdvdWd1b3lpbi5jbg== @@ -175,6 +180,7 @@ dongle.Decode.FromBytes([]byte("👟👜👣👣👦🐗👮👦👩👣👛")). ``` ##### SafeURL 编码、解码 + ```go // 对 url 字符进行转义编码,输出字符串 dongle.Encode.FromString("www.gouguoyin.cn?sex=男&age=18").BySafeURL().ToString() // www.gouguoyin.cn%3Fsex%3D%E7%94%B7%26age%3D18 @@ -188,6 +194,7 @@ dongle.Decode.FromBytes([]byte("www.gouguoyin.cn%3Fsex%3D%E7%94%B7%26age%3D18")) ``` ##### Morse(摩斯) 编码、解码 + > 默认分隔符是 `/` ```go @@ -235,6 +242,7 @@ dongle.Encrypt.FromBytes([]byte("hello world")).ByMd4().ToBase64Bytes() // []byt ``` ##### Md5 加密 + ```go // 对字符串进行 md5 加密,输出经过 hex 编码的字符串 dongle.Encrypt.FromString("hello world").ByMd5().ToHexString() // 5eb63bbbe01eeed093cb22bb8f5acdc3 @@ -248,6 +256,7 @@ dongle.Encrypt.FromBytes([]byte("hello world")).ByMd5().ToBase64Bytes() // []byt ``` ##### Sha1 加密 + ```go // 对字符串进行 sha1 加密,输出经过 hex 编码的字符串 dongle.Encrypt.FromString("hello world").BySha1().ToHexString() // 2aae6c35c94fcfb415dbe95f408b9ce91ee846ed @@ -261,6 +270,7 @@ dongle.Encrypt.FromBytes([]byte("hello world")).BySha1().ToBase64Bytes() // []by ``` ##### Sha3 加密 + > 包含 sha3-224, sha3-256, sha3-384, sha3-512 ```go @@ -317,6 +327,7 @@ dongle.Encrypt.FromBytes([]byte("hello world")).BySha224().ToBase64Bytes() // [] ``` ##### Sha256 加密 + ```go // 对字符串进行 sha256 加密,输出经过 hex 编码的字符串 dongle.Encrypt.FromString("hello world").BySha256().ToHexString() // b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9 @@ -330,6 +341,7 @@ dongle.Encrypt.FromBytes([]byte("hello world")).BySha256().ToBase64Bytes() // [] ``` ##### Sha384 加密 + ```go // 对字符串进行 sha384 加密,输出经过 hex 编码的字符串 dongle.Encrypt.FromString("hello world").BySha384().ToHexString() // fdbd8e75a67f29f701a4e040385e2e23986303ea10239211af907fcbb83578b3e417cb71ce646efd0819dd8c088de1bd @@ -594,7 +606,7 @@ dongle.Encrypt.FromBytes([]byte("hello world")).ByHmacSm3([]byte("dongle")).ToBa ```go cipher := dongle.NewCipher() cipher.SetMode(dongle.CBC) // CBC、CFB、OFB、CTR、ECB -cipher.SetPadding(dongle.PKCS7) // No、Zero、PKCS5、PKCS7 +cipher.SetPadding(dongle.PKCS7) // No、Zero、PKCS5、PKCS7、AnsiX923、ISO97971 cipher.SetKey("0123456789abcdef") // key 长度必须是 16、24 或 32 字节 cipher.SetIV("0123456789abcdef") // iv 长度必须是 16 字节,ECB 模式不需要设置 iv @@ -634,8 +646,8 @@ dongle.Decrypt.FromBase64Bytes(()byte("wem0Upqsl5MBD0Z39jWO/g==")).ByAes(cipher) ```go cipher := dongle.NewCipher() cipher.SetMode(dongle.CBC) // CBC、ECB、CFB、OFB、CTR -cipher.SetPadding(dongle.PKCS7) // No、Zero、PKCS5、PKCS7 -cipher.SetKey("12345678") // key 长度必须是 8 字节 +cipher.SetPadding(dongle.PKCS7) // No、Zero、PKCS5、PKCS7、AnsiX923、ISO97971 +cipher.SetKey("12345678") // key 长度必须是 8 字节 cipher.SetIV("12345678") // iv 长度必须是 8 字节 // 对字符串进行 des 加密,输出未经编码的原始字符串 @@ -674,7 +686,7 @@ dongle.Decrypt.FromBase64Bytes(()byte("CyqS6B+0nOGkMmaqyup7gQ==")).ByDes(cipher) ```go cipher := dongle.NewCipher() cipher.SetMode(dongle.CBC) // CBC, CFB, CTR, ECB, OFB -cipher.SetPadding(dongle.PKCS7) // No、Zero、PKCS5、PKCS7 +cipher.SetPadding(dongle.PKCS7) // No、Zero、PKCS5、PKCS7、AnsiX923、ISO97971 cipher.SetKey("123456781234567812345678") // key 长度必须是 24 cipher.SetIV("12345678") // iv 长度必须是 8 @@ -684,9 +696,9 @@ rawString := dongle.Encrypt.FromString("hello world").By3Des(cipher).ToRawString dongle.Decrypt.FromRawString(rawString).By3Des(cipher).ToString() // hello world // 对字符串进行 3des 加密,输出经过 hex 编码的字符串 -dongle.Encrypt.FromString("hello world").By3Des(cipher).ToHexString() // 0b2a92e81fb49ce1a43266aacaea7b81 +dongle.Encrypt.FromString("hello world").By3Des(cipher).ToHexString() // 92c3724d720b59982d21aab9a7bb9f40 // 对经过 hex 编码的字符串进行 3des 解密,输出字符串 -dongle.Decrypt.FromHexString("0b2a92e81fb49ce1a43266aacaea7b81").By3Des(cipher).ToString() // hello world +dongle.Decrypt.FromHexString("92c3724d720b59982d21aab9a7bb9f40").By3Des(cipher).ToString() // hello world // 对字符串进行 3des 加密,输出经过 base64 编码的字符串 dongle.Encrypt.FromString("hello world").By3Des(cipher).ToBase64String() // CyqS6B+0nOGkMmaqyup7gQ== @@ -699,9 +711,9 @@ rawBytes := dongle.Encrypt.FromBytes([]byte("hello world")).By3Des(cipher).ToRaw dongle.Decrypt.FromRawBytes(rawBytes).By3Des(cipher).ToBytes() // []byte("hello world") // 对字节切片进行 3des 加密,输出经过 hex 编码的字节切片 -dongle.Encrypt.FromBytes([]byte("hello world")).By3Des(cipher).ToHexBytes() // []byte("0b2a92e81fb49ce1a43266aacaea7b81") +dongle.Encrypt.FromBytes([]byte("hello world")).By3Des(cipher).ToHexBytes() // []byte("92c3724d720b59982d21aab9a7bb9f40") // 对经过 hex 编码的字节切片进行 3des 解密,输出字符串 -dongle.Decrypt.FromHexBytes([]byte("0b2a92e81fb49ce1a43266aacaea7b81")).By3Des(cipher).ToBytes() // []byte("hello world") +dongle.Decrypt.FromHexBytes([]byte("92c3724d720b59982d21aab9a7bb9f40")).By3Des(cipher).ToBytes() // []byte("hello world") // 对字节切片进行 3des 加密,输出经过 base64 编码的字节切片 dongle.Encrypt.FromBytes([]byte("hello world")).By3Des(cipher).ToBase64Bytes() // []byte("CyqS6B+0nOGkMmaqyup7gQ==") @@ -709,6 +721,46 @@ dongle.Encrypt.FromBytes([]byte("hello world")).By3Des(cipher).ToBase64Bytes() / dongle.Decrypt.FromBase64Bytes(()byte("CyqS6B+0nOGkMmaqyup7gQ==")).By3Des(cipher).ToBytes() // []byte("hello world") ``` +##### Blowfish 加密、解密 + +```go +cipher := dongle.NewCipher() +cipher.SetMode(dongle.CBC) // CBC、CFB、OFB、CTR、ECB +cipher.SetPadding(dongle.PKCS7) // No、Zero、PKCS5、PKCS7、AnsiX923、ISO97971 +cipher.SetKey("0123456789abcdef") // key 长度必须是 1-56 字节 +cipher.SetIV("12345678") // iv 长度必须是 8 字节,ECB 模式不需要设置 iv + +// 对字符串进行 blowfish 加密,输出未经编码的原始字符串 +rawString := dongle.Encrypt.FromString("hello world").ByBlowfish(cipher).ToRawString() +// 对未经编码的原始字符串进行 blowfish 解密,输出字符串 +dongle.Decrypt.FromRawString(rawString).ByBlowfish(cipher).ToString() // hello world + +// 对字符串进行 blowfish 加密,输出经过 hex 编码的字符串 +dongle.Encrypt.FromString("hello world").ByBlowfish(cipher).ToHexString() // c1e9b4529aac9793010f4677f6358efe +// 对经过 hex 编码的字符串进行 blowfish 解密,输出字符串 +dongle.Decrypt.FromHexString("c1e9b4529aac9793010f4677f6358efe").ByBlowfish(cipher).ToString() // hello world + +// 对字符串进行 blowfish 加密,输出经过 base64 编码的字符串 +dongle.Encrypt.FromString("hello world").ByBlowfish(cipher).ToBase64String() // ksNyTXILWZgtIaq5p7ufQA== +// 对经过 base64 编码的字符串进行 blowfish 解密,输出字符串 +dongle.Decrypt.FromBase64String("ksNyTXILWZgtIaq5p7ufQA==").ByBlowfish(cipher).ToString() // hello world + +// 对字节切片进行 blowfish 加密,输出未经编码的原始字节切片 +rawBytes := dongle.Encrypt.FromBytes([]byte("hello world")).ByBlowfish(cipher).ToRawBytes() +// 对未经编码的原始字节切片进行 blowfish 解密,输出字节切片 +dongle.Decrypt.FromRawBytes(rawBytes).ByBlowfish(cipher).ToBytes() // []byte("hello world") + +// 对字节切片进行 blowfish 加密,输出经过 hex 编码的字节切片 +dongle.Encrypt.FromBytes([]byte("hello world")).ByBlowfish(cipher).ToHexBytes() // []byte("c1e9b4529aac9793010f4677f6358efe") +// 对经过 hex 编码的字节切片进行 blowfish 解密,输出字节切片 +dongle.Decrypt.FromHexBytes([]byte("c1e9b4529aac9793010f4677f6358efe")).ByBlowfish(cipher).ToBytes() // []byte("hello world") + +// 对字节切片进行 blowfish 加密,输出经过 base64 编码的字节切片 +dongle.Encrypt.FromBytes([]byte("hello world")).ByBlowfish(cipher).ToBase64Bytes() // []byte("ksNyTXILWZgtIaq5p7ufQA==") +// 对经过 base64 编码的字节切片进行 blowfish 解密,输出字节切片 +dongle.Decrypt.FromBase64Bytes(()byte("ksNyTXILWZgtIaq5p7ufQA==")).ByBlowfish(cipher).ToBytes() // []byte("hello world") +``` + ##### Rsa 加密、解密 ```go @@ -788,6 +840,7 @@ dongle.Decrypt.FromBase64Bytes(cipherText.ToBase64Bytes()).ByRsa(pkcs8PrivateKey ``` ##### Tea 加密、解密 + > 迭代轮次(rounds) 必须是偶数,默认是 64 ```go @@ -1059,6 +1112,7 @@ rsa: invalid public key, please make sure the public key is valid - [x] Tea 加密、解密 - [ ] Xtea 加密、解密 - [x] Aes 加密、解密 +- [x] Blowfish 加密、解密 - [x] Des 加密、解密 - [x] 3Des 加密、解密 - [x] Rsa 加密、解密 @@ -1074,23 +1128,26 @@ rsa: invalid public key, please make sure the public key is valid - [ ] Dsa 签名、验签 ### 参考项目 + * [javascript/crypto-js](https://github.com/brix/crypto-js) * [nodejs/crypto](https://nodejs.org/api/crypto.html) * [java/jasypt](https://github.com/jasypt/jasypt) * [python/pycryptodome](https://github.com/Legrandin/pycryptodome) ### 在线网站 + * [www.ssleye.com](https://www.ssleye.com/ssltool) * [base62.js.org](https://base62.js.org) * [www.sojson.com](https://www.sojson.com/encrypt.html) -* [tool.chacuo.net](https://tool.chacuo.net/cryptaes) +* [tool.chacuo.net](http://tool.chacuo.net/cryptaes) * [www.oktools.net](https://oktools.net/aes) ### 赞助 + `Dongle` 是一个非商业开源项目, 如果你想支持 `Dongle`, 你可以为开发者 [购买一杯咖啡](https://www.gouguoyin.com/zanzhu.html) ### 致谢 `Dongle`已获取免费的 JetBrains 开源许可证,在此表示感谢 -JetBrains +JetBrains \ No newline at end of file diff --git a/README.md b/README.md index 1712c6a..e01ab8d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # dongle # + [![Carbon Release](https://img.shields.io/github/release/golang-module/dongle.svg)](https://github.com/golang-module/dongle/releases) [![Go Build](https://github.com/golang-module/dongle/actions/workflows/test.yml/badge.svg)](https://github.com/golang-module/dongle/actions) [![Go Report Card](https://goreportcard.com/badge/github.com/golang-module/dongle)](https://goreportcard.com/report/github.com/golang-module/dongle) @@ -9,7 +10,8 @@ English | [简体中文](README.cn.md) ### Introduction -A simple, semantic and developer-friendly golang package for encoding&decoding and encryption&decryption + +A simple, semantic and developer-friendly golang package for encoding&decoding, encryption&decryption and signature&verification `Dongle` has been included by [awesome-go](https://github.com/avelino/awesome-go#security "awesome-go"), if you think it is helpful, please give me a star @@ -19,6 +21,7 @@ it is helpful, please give me a star [gitee.com/golang-module/dongle](https://gitee.com/golang-module/dongle "gitee.com/golang-module/dongle") ### Installation + ```go // By github go get -u github.com/golang-module/dongle @@ -125,6 +128,7 @@ dongle.Decode.FromBytes([]byte("aGVsbG8gd29ybGQ=")).ByBase64().ToBytes() // []by ``` ##### Encode and decode by base64URL + ```go // Encode by base64 from url string and output string dongle.Encode.FromString("www.gouguoyin.cn").ByBase64URL().ToString() // d3d3LmdvdWd1b3lpbi5jbg== @@ -138,6 +142,7 @@ dongle.Decode.FromBytes([]byte("d3d3LmdvdWd1b3lpbi5jbg==")).ByBase64URL().ToByte ``` ##### Encode and decode by base85 + ```go // Encode by base85 from string and output string dongle.Encode.FromString("hello world").ByBase85().ToString() // BOu!rD]j7BEbo7 @@ -151,6 +156,7 @@ dongle.Decode.FromBytes([]byte("BOu!rD]j7BEbo7")).ByBase85().ToBytes() // []byte ``` ##### Encode and decode by base91 + ```go // Encode by base91 from string and output string dongle.Encode.FromString("hello world").ByBase91().ToString() // TPwJh>Io2Tv!lE @@ -164,6 +170,7 @@ dongle.Decode.FromBytes([]byte("TPwJh>Io2Tv!lE")).ByBase91().ToBytes() // []byte ``` ##### Encode and decode by base100 + ```go // Encode by base100 from string and output string dongle.Encode.FromString("hello world").ByBase100().ToString() // 👟👜👣👣👦🐗👮👦👩👣👛 @@ -177,6 +184,7 @@ dongle.Decode.FromBytes([]byte("👟👜👣👣👦🐗👮👦👩👣👛")). ``` ##### Encode and decode by safeURL + ```go // Encode by escape from url string and output string dongle.Encode.FromString("www.gouguoyin.cn?sex=男&age=18").BySafeURL().ToString() // www.gouguoyin.cn%3Fsex%3D%E7%94%B7%26age%3D18 @@ -190,6 +198,7 @@ dongle.Decode.FromBytes([]byte("www.gouguoyin.cn%3Fsex%3D%E7%94%B7%26age%3D18")) ``` ##### Encode and decode by morse + > The default value of separator is `/` ```go @@ -236,6 +245,7 @@ dongle.Encrypt.FromBytes([]byte("hello world")).ByMd4().ToBase64Bytes() // []byt ``` ##### Encrypt by md5 + ```go // Encrypt by md5 from string and output string with hex encoding dongle.Encrypt.FromString("hello world").ByMd5().ToHexString() // 5eb63bbbe01eeed093cb22bb8f5acdc3 @@ -249,6 +259,7 @@ dongle.Encrypt.FromBytes([]byte("hello world")).ByMd5().ToBase64Bytes() // []byt ``` ##### Encrypt by sha1 + ```go // Encrypt by sha1 from string and output string with hex encoding dongle.Encrypt.FromString("hello world").BySha1().ToHexString() // 2aae6c35c94fcfb415dbe95f408b9ce91ee846ed @@ -262,6 +273,7 @@ dongle.Encrypt.FromBytes([]byte("hello world")).BySha1().ToBase64Bytes() // []by ``` ##### Encrypt by sha3 + > include sha3-224, sha3-256, sha3-384, sha3-512 ```go @@ -598,7 +610,7 @@ dongle.Encrypt.FromBytes([]byte("hello world")).ByHmacSm3().ToBase64Bytes() // [ ```go cipher := dongle.NewCipher() cipher.SetMode(dongle.CBC) // CBC、CFB、OFB、CTR、ECB -cipher.SetPadding(dongle.PKCS7) // No、Zero、PKCS5、PKCS7 +cipher.SetPadding(dongle.PKCS7) // No、Zero、PKCS5、PKCS7、AnsiX923、ISO97971 cipher.SetKey("0123456789abcdef") // key must be 16, 24 or 32 bytes cipher.SetIV("0123456789abcdef") // iv must be 16 bytes (ECB mode doesn't require setting iv) @@ -639,8 +651,8 @@ dongle.Decrypt.FromBase64Bytes(()byte("wem0Upqsl5MBD0Z39jWO/g==")).ByAes(cipher) ```go cipher := dongle.NewCipher() cipher.SetMode(dongle.CBC) // CBC、ECB、CFB、OFB、CTR -cipher.SetPadding(dongle.PKCS7) // No、Zero、PKCS5、PKCS7 -cipher.SetKey("12345678") // key must be 8 bytes +cipher.SetPadding(dongle.PKCS7) // No、Zero、PKCS5、PKCS7、AnsiX923、ISO97971 +cipher.SetKey("12345678") // key must be 8 bytes cipher.SetIV("12345678") // iv must be 8 bytes // Encrypt by des from string and output raw string @@ -679,7 +691,7 @@ dongle.Decrypt.FromBase64Bytes(()byte("CyqS6B+0nOGkMmaqyup7gQ==")).ByDes(cipher) ```go cipher := dongle.NewCipher() cipher.SetMode(dongle.CBC) // CBC、ECB、CFB、OFB、CTR -cipher.SetPadding(dongle.PKCS7) // No、Zero、PKCS5、PKCS7 +cipher.SetPadding(dongle.PKCS7) // No、Zero、PKCS5、PKCS7、AnsiX923、ISO97971 cipher.SetKey("123456781234567812345678") // key must be 24 bytes cipher.SetIV("12345678") // iv must be 8 bytes @@ -714,6 +726,46 @@ dongle.Encrypt.FromBytes([]byte("hello world")).By3Des(cipher).ToBase64Bytes() / dongle.Decrypt.FromBase64Bytes(()byte("CyqS6B+0nOGkMmaqyup7gQ==")).By3Des(cipher).ToBytes() // []byte("hello world") ``` +##### Encrypt and decrypt by blowfish + +```go +cipher := dongle.NewCipher() +cipher.SetMode(dongle.CBC) // CBC、CFB、OFB、CTR、ECB +cipher.SetPadding(dongle.PKCS7) // No、Zero、PKCS5、PKCS7、AnsiX923、ISO97971 +cipher.SetKey("0123456789abcdef") // key must from 1 to 56 bytes +cipher.SetIV("12345678") // iv must be 8 bytes + +// Encrypt by blowfish from string and output raw string +rawString := dongle.Encrypt.FromString("hello world").ByBlowfish(cipher).ToRawString() +// Decrypt by blowfish from raw string and output string +dongle.Decrypt.FromRawString(rawString).ByBlowfish(cipher).ToString() // hello world + +// Encrypt by blowfish from string and output string with hex encoding +dongle.Encrypt.FromString("hello world").ByBlowfish(cipher).ToHexString() // c1e9b4529aac9793010f4677f6358efe +// Decrypt by blowfish from string with hex encoding and output string +dongle.Decrypt.FromHexString("c1e9b4529aac9793010f4677f6358efe").ByBlowfish(cipher).ToString() // hello world + +// Encrypt by blowfish from string and output string with base64 encoding +dongle.Encrypt.FromString("hello world").ByBlowfish(cipher).ToBase64String() // ksNyTXILWZgtIaq5p7ufQA== +// Decrypt by blowfish from string with base64 encoding and output string +dongle.Decrypt.FromBase64String("ksNyTXILWZgtIaq5p7ufQA==").ByBlowfish(cipher).ToString() // hello world + +// Encrypt by blowfish from byte slice and output raw byte slice +rawBytes := dongle.Encrypt.FromBytes([]byte("hello world")).ByBlowfish(cipher).ToRawBytes() +// Decrypt by blowfish from raw byte slice and output byte slice +dongle.Decrypt.FromRawBytes(rawBytes).ByBlowfish(cipher).ToBytes() // []byte("hello world") + +// Encrypt by blowfish from byte slice and output byte slice with hex encoding +dongle.Encrypt.FromBytes([]byte("hello world")).ByBlowfish(cipher).ToHexBytes() // []byte("c1e9b4529aac9793010f4677f6358efe") +// Decrypt by blowfish from byte slice with hex encoding and output byte slice +dongle.Decrypt.FromHexBytes([]byte("c1e9b4529aac9793010f4677f6358efe")).ByBlowfish(cipher).ToBytes() // []byte("hello world") + +// Encrypt by blowfish from byte slice and output byte slice with base64 encoding +dongle.Encrypt.FromBytes([]byte("hello world")).ByBlowfish(cipher).ToBase64Bytes() // []byte("ksNyTXILWZgtIaq5p7ufQA==") +// Decrypt by blowfish from byte slice with base64 encoding and output byte slice +dongle.Decrypt.FromBase64Bytes(()byte("ksNyTXILWZgtIaq5p7ufQA==")).ByBlowfish(cipher).ToBytes() // []byte("hello world") +``` + ##### Encrypt and decrypt by rsa ```go @@ -793,6 +845,7 @@ dongle.Decrypt.FromBase64Bytes(cipherText.ToBase64Bytes()).ByRsa(pkcs8PrivateKey ``` ##### Encrypt and decrypt by tea + > Rounds must be even, the default value is 64 ```go @@ -1056,6 +1109,7 @@ rsa: invalid public key, please make sure the public key is valid - [x] Encryption and decryption by Tea - [ ] Encryption and decryption by Xtea - [x] Encryption and decryption by Aes +- [x] Encryption and decryption by Blowfish - [x] Encryption and decryption by Des - [x] Encryption and decryption by 3Des - [x] Encryption and decryption by Rsa @@ -1071,25 +1125,26 @@ rsa: invalid public key, please make sure the public key is valid - [ ] Sign and verify by Dsa ### References + * [javascript/crypto-js](https://github.com/brix/crypto-js) * [nodejs/crypto](https://nodejs.org/api/crypto.html) * [java/jasypt](https://github.com/jasypt/jasypt) * [python/pycryptodome](https://github.com/Legrandin/pycryptodome) ### Online website + * [www.ssleye.com](https://www.ssleye.com/ssltool) * [base62.js.org](https://base62.js.org) * [www.sojson.com](https://www.sojson.com/encrypt.html) -* [tool.chacuo.net](https://tool.chacuo.net/cryptaes) +* [tool.chacuo.net](http://tool.chacuo.net/cryptaes) * [www.oktools.net](https://oktools.net/aes) ### Sponsors -`Dongle` is a non-commercial open source project. If you want to support `Dongle`, you -can [buy a cup of coffee](https://opencollective.com/go-carbon) for developer. + +`Dongle` is a non-commercial open source project. If you want to support `Dongle`, you can [buy a cup of coffee](https://opencollective.com/go-carbon) for developer. ### Thanks -`Dongle` had been being developed with GoLand under the free JetBrains Open Source license, I would like to express my -thanks here. +`Dongle` had been being developed with GoLand under the free JetBrains Open Source license, I would like to express my thanks here. -JetBrains +JetBrains \ No newline at end of file diff --git a/aes.go b/aes.go index bfb164e..a8ce45f 100644 --- a/aes.go +++ b/aes.go @@ -6,7 +6,7 @@ import ( // ByAes encrypts by aes. // 通过 aes 加密 -func (e encrypter) ByAes(c *Cipher) encrypter { +func (e Encrypter) ByAes(c *Cipher) Encrypter { block, err := aes.NewCipher(c.key) if err != nil { e.Error = invalidAesKeyError() @@ -26,7 +26,7 @@ func (e encrypter) ByAes(c *Cipher) encrypter { // ByAes decrypts by aes. // 通过 aes 解密 -func (d decrypter) ByAes(c *Cipher) decrypter { +func (d Decrypter) ByAes(c *Cipher) Decrypter { if d.Error != nil { return d } diff --git a/aes_test.go b/aes_test.go index c8c5ce6..8c94ea0 100755 --- a/aes_test.go +++ b/aes_test.go @@ -18,35 +18,45 @@ var aesTests = []struct { toHex string toBase64 string }{ - {CBC, "", "", "", ""}, + {CBC, PKCS7, "", "", ""}, {CBC, No, "hello world, go!", "77aa39926f9b2f3f22254bfd422fa75d", "d6o5km+bLz8iJUv9Qi+nXQ=="}, {CBC, Zero, "hello world", "889935b7a0c64b0333d713cafaee08fe", "iJk1t6DGSwMz1xPK+u4I/g=="}, {CBC, PKCS5, "hello world", "c1e9b4529aac9793010f4677f6358efe", "wem0Upqsl5MBD0Z39jWO/g=="}, {CBC, PKCS7, "hello world", "c1e9b4529aac9793010f4677f6358efe", "wem0Upqsl5MBD0Z39jWO/g=="}, + {CBC, AnsiX923, "hello world", "19267ee4e262addb6657840738d3b93d", "GSZ+5OJirdtmV4QHONO5PQ=="}, + {CBC, ISO97971, "hello world", "fd4fd654217962e0cfa285aa4da354e7", "/U/WVCF5YuDPooWqTaNU5w=="}, - {CFB, "", "", "", ""}, + {CFB, PKCS7, "", "", ""}, {CFB, No, "hello world, go!", "1a1712e471fc8a6e72cb7c44596eda44", "GhcS5HH8im5yy3xEWW7aRA=="}, {CFB, Zero, "hello world", "1a1712e471fc8a6e72cb7c687909b565", "GhcS5HH8im5yy3xoeQm1ZQ=="}, {CFB, PKCS5, "hello world", "1a1712e471fc8a6e72cb7c6d7c0cb060", "GhcS5HH8im5yy3xtfAywYA=="}, {CFB, PKCS7, "hello world", "1a1712e471fc8a6e72cb7c6d7c0cb060", "GhcS5HH8im5yy3xtfAywYA=="}, + {CFB, AnsiX923, "hello world", "1a1712e471fc8a6e72cb7c687909b560", "GhcS5HH8im5yy3xoeQm1YA=="}, + {CFB, ISO97971, "hello world", "1a1712e471fc8a6e72cb7ce87909b565", "GhcS5HH8im5yy3zoeQm1ZQ=="}, - {OFB, "", "", "", ""}, + {OFB, PKCS7, "", "", ""}, {OFB, No, "hello world, go!", "1a1712e471fc8a6e72cb7c44596eda44", "GhcS5HH8im5yy3xEWW7aRA=="}, {OFB, Zero, "hello world", "1a1712e471fc8a6e72cb7c687909b565", "GhcS5HH8im5yy3xoeQm1ZQ=="}, {OFB, PKCS5, "hello world", "1a1712e471fc8a6e72cb7c6d7c0cb060", "GhcS5HH8im5yy3xtfAywYA=="}, {OFB, PKCS7, "hello world", "1a1712e471fc8a6e72cb7c6d7c0cb060", "GhcS5HH8im5yy3xtfAywYA=="}, + {OFB, AnsiX923, "hello world", "1a1712e471fc8a6e72cb7c687909b560", "GhcS5HH8im5yy3xoeQm1YA=="}, + {OFB, ISO97971, "hello world", "1a1712e471fc8a6e72cb7ce87909b565", "GhcS5HH8im5yy3zoeQm1ZQ=="}, - {CTR, "", "", "", ""}, + {CTR, PKCS7, "", "", ""}, {CTR, No, "hello world, go!", "1a1712e471fc8a6e72cb7c44596eda44", "GhcS5HH8im5yy3xEWW7aRA=="}, {CTR, Zero, "hello world", "1a1712e471fc8a6e72cb7c687909b565", "GhcS5HH8im5yy3xoeQm1ZQ=="}, {CTR, PKCS5, "hello world", "1a1712e471fc8a6e72cb7c6d7c0cb060", "GhcS5HH8im5yy3xtfAywYA=="}, {CTR, PKCS7, "hello world", "1a1712e471fc8a6e72cb7c6d7c0cb060", "GhcS5HH8im5yy3xtfAywYA=="}, + {CTR, AnsiX923, "hello world", "1a1712e471fc8a6e72cb7c687909b560", "GhcS5HH8im5yy3xoeQm1YA=="}, + {CTR, ISO97971, "hello world", "1a1712e471fc8a6e72cb7ce87909b565", "GhcS5HH8im5yy3zoeQm1ZQ=="}, - {ECB, "", "", "", ""}, + {ECB, PKCS7, "", "", ""}, {ECB, No, "hello world, go!", "f82a4c0db7a82f70c7fa84c39fa7627b", "+CpMDbeoL3DH+oTDn6diew=="}, {ECB, Zero, "hello world", "769c326290511c93bd59bba9c24d8904", "dpwyYpBRHJO9Wbupwk2JBA=="}, {ECB, PKCS5, "hello world", "8169bed4ef49a8874559c5b200daade7", "gWm+1O9JqIdFWcWyANqt5w=="}, {ECB, PKCS7, "hello world", "8169bed4ef49a8874559c5b200daade7", "gWm+1O9JqIdFWcWyANqt5w=="}, + {ECB, AnsiX923, "hello world", "1e33dfd0c42e440761065e2705e7f0f7", "HjPf0MQuRAdhBl4nBefw9w=="}, + {ECB, ISO97971, "hello world", "49153a0969bae6246d1f6f7e75628eea", "SRU6CWm65iRtH29+dWKO6g=="}, } func TestAes_Encrypt_String(t *testing.T) { @@ -54,15 +64,15 @@ func TestAes_Encrypt_String(t *testing.T) { raw := Decode.FromString(test.toHex).ByHex().ToString() e := Encrypt.FromString(test.input).ByAes(getCipher(test.mode, test.padding, aesKey, aesIV)) - t.Run(fmt.Sprintf(string(test.mode)+"_raw_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_raw_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, raw, e.ToRawString()) }) - t.Run(fmt.Sprintf(string(test.mode)+"_hex_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_hex_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, test.toHex, e.ToHexString()) }) - t.Run(fmt.Sprintf(string(test.mode)+"_base64_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_base64_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, test.toBase64, e.ToBase64String()) }) @@ -74,7 +84,7 @@ func TestAes_Decrypt_String(t *testing.T) { raw := Decode.FromString(test.toHex).ByHex().ToString() e := Decrypt.FromRawString(raw).ByAes(getCipher(test.mode, test.padding, aesKey, aesIV)) - t.Run(fmt.Sprintf(string(test.mode)+"_raw_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_raw_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, test.input, e.ToString()) assert.Equal(t, test.input, fmt.Sprintf("%s", e)) @@ -84,7 +94,7 @@ func TestAes_Decrypt_String(t *testing.T) { for index, test := range aesTests { e := Decrypt.FromHexString(test.toHex).ByAes(getCipher(test.mode, test.padding, aesKey, aesIV)) - t.Run(fmt.Sprintf(string(test.mode)+"_hex_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_hex_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, test.input, e.ToString()) assert.Equal(t, test.input, fmt.Sprintf("%s", e)) @@ -94,7 +104,7 @@ func TestAes_Decrypt_String(t *testing.T) { for index, test := range aesTests { e := Decrypt.FromBase64String(test.toBase64).ByAes(getCipher(test.mode, test.padding, aesKey, aesIV)) - t.Run(fmt.Sprintf(string(test.mode)+"_base64_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_base64_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, test.input, e.ToString()) assert.Equal(t, test.input, fmt.Sprintf("%s", e)) @@ -107,15 +117,15 @@ func TestAes_Encrypt_Bytes(t *testing.T) { raw := Decode.FromBytes([]byte(test.toHex)).ByHex().ToBytes() e := Encrypt.FromBytes([]byte(test.input)).ByAes(getCipher(test.mode, test.padding, []byte(aesKey), []byte(aesIV))) - t.Run(fmt.Sprintf(string(test.mode)+"_raw_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_raw_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, raw, e.ToRawBytes()) }) - t.Run(fmt.Sprintf(string(test.mode)+"_hex_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_hex_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, []byte(test.toHex), e.ToHexBytes()) }) - t.Run(fmt.Sprintf(string(test.mode)+"_base64_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_base64_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, []byte(test.toBase64), e.ToBase64Bytes()) }) @@ -127,7 +137,7 @@ func TestAes_Decrypt_Bytes(t *testing.T) { raw := Decode.FromBytes([]byte(test.toHex)).ByHex().ToBytes() e := Decrypt.FromRawBytes(raw).ByAes(getCipher(test.mode, test.padding, []byte(aesKey), []byte(aesIV))) - t.Run(fmt.Sprintf(string(test.mode)+"_raw_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_raw_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, []byte(test.input), e.ToBytes()) }) @@ -136,7 +146,7 @@ func TestAes_Decrypt_Bytes(t *testing.T) { for index, test := range aesTests { e := Decrypt.FromHexBytes([]byte(test.toHex)).ByAes(getCipher(test.mode, test.padding, []byte(aesKey), []byte(aesIV))) - t.Run(fmt.Sprintf(string(test.mode)+"_hex_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_hex_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, []byte(test.input), e.ToBytes()) }) @@ -145,7 +155,7 @@ func TestAes_Decrypt_Bytes(t *testing.T) { for index, test := range aesTests { e := Decrypt.FromBase64Bytes([]byte(test.toBase64)).ByAes(getCipher(test.mode, test.padding, []byte(aesKey), []byte(aesIV))) - t.Run(fmt.Sprintf(string(test.mode)+"_base64_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_base64_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, []byte(test.input), e.ToBytes()) }) diff --git a/baseX.go b/baseX.go index 4575447..34a08fe 100644 --- a/baseX.go +++ b/baseX.go @@ -14,7 +14,7 @@ import ( // ByHex encodes by hex. // 通过 hex 编码 -func (e encoder) ByHex() encoder { +func (e Encoder) ByHex() Encoder { buf := make([]byte, hex.EncodedLen(len(e.src))) hex.Encode(buf, e.src) e.dst = buf @@ -23,7 +23,7 @@ func (e encoder) ByHex() encoder { // ByHex decodes by hex. // 通过 hex 解码 -func (d decoder) ByHex() decoder { +func (d Decoder) ByHex() Decoder { buf := make([]byte, hex.DecodedLen(len(d.src))) n, err := hex.Decode(buf, d.src) if n > 0 { @@ -38,13 +38,13 @@ func (d decoder) ByHex() decoder { // ByBase16 encodes by base16. // 通过 base16 编码 -func (e encoder) ByBase16() encoder { +func (e Encoder) ByBase16() Encoder { return e.ByHex() } // ByBase16 decodes by base16. // 通过 base16 解码 -func (d decoder) ByBase16() decoder { +func (d Decoder) ByBase16() Decoder { if d.ByHex().Error != nil { d.Error = invalidDecodingError("base16") return d @@ -54,7 +54,7 @@ func (d decoder) ByBase16() decoder { // ByBase32 encodes by base32. // 通过 base32 编码 -func (e encoder) ByBase32() encoder { +func (e Encoder) ByBase32() Encoder { if len(e.src) == 0 { return e } @@ -66,7 +66,7 @@ func (e encoder) ByBase32() encoder { // ByBase32 decodes by base32. // 通过 base32 解码 -func (d decoder) ByBase32() decoder { +func (d Decoder) ByBase32() Decoder { if len(d.src) == 0 { return d } @@ -82,7 +82,7 @@ func (d decoder) ByBase32() decoder { // ByBase58 encodes by base58. // 通过 base58 编码 -func (e encoder) ByBase58() encoder { +func (e Encoder) ByBase58() Encoder { if len(e.src) == 0 { return e } @@ -92,7 +92,7 @@ func (e encoder) ByBase58() encoder { // ByBase58 decodes by base58. // 通过 base58 解码 -func (d decoder) ByBase58() decoder { +func (d Decoder) ByBase58() Decoder { if len(d.src) == 0 { return d } @@ -102,7 +102,7 @@ func (d decoder) ByBase58() decoder { // ByBase62 encodes by base91. // 通过 base62 编码 -func (e encoder) ByBase62() encoder { +func (e Encoder) ByBase62() Encoder { if len(e.src) == 0 { return e } @@ -112,7 +112,7 @@ func (e encoder) ByBase62() encoder { // ByBase62 decodes by base91. // 通过 base62 解码 -func (d decoder) ByBase62() decoder { +func (d Decoder) ByBase62() Decoder { if len(d.src) == 0 { return d } @@ -126,7 +126,7 @@ func (d decoder) ByBase62() decoder { // ByBase64 encodes by base64. // 通过 base64 编码 -func (e encoder) ByBase64() encoder { +func (e Encoder) ByBase64() Encoder { if len(e.src) == 0 { return e } @@ -138,7 +138,7 @@ func (e encoder) ByBase64() encoder { // ByBase64 decodes by base64. // 通过 base64 解码 -func (d decoder) ByBase64() decoder { +func (d Decoder) ByBase64() Decoder { if len(d.src) == 0 { return d } @@ -154,7 +154,7 @@ func (d decoder) ByBase64() decoder { // ByBase64URL encodes by base64 for url. // 通过 base64 对 url 编码 -func (e encoder) ByBase64URL() encoder { +func (e Encoder) ByBase64URL() Encoder { if len(e.src) == 0 { return e } @@ -166,7 +166,7 @@ func (e encoder) ByBase64URL() encoder { // ByBase64URL decodes by base64 for url. // 通过 base64 对 url 解码 -func (d decoder) ByBase64URL() decoder { +func (d Decoder) ByBase64URL() Decoder { if len(d.src) == 0 { return d } @@ -182,7 +182,7 @@ func (d decoder) ByBase64URL() decoder { // ByBase85 encodes by base85. // 通过 base85 编码 -func (e encoder) ByBase85() encoder { +func (e Encoder) ByBase85() Encoder { if len(e.src) == 0 { return e } @@ -194,7 +194,7 @@ func (e encoder) ByBase85() encoder { // ByBase85 decodes by base85. // 通过 base85 解码 -func (d decoder) ByBase85() decoder { +func (d Decoder) ByBase85() Decoder { if len(d.src) == 0 { return d } @@ -210,7 +210,7 @@ func (d decoder) ByBase85() decoder { // ByBase91 encodes by base91. // 通过 base91 编码 -func (e encoder) ByBase91() encoder { +func (e Encoder) ByBase91() Encoder { if len(e.src) == 0 { return e } @@ -222,7 +222,7 @@ func (e encoder) ByBase91() encoder { // ByBase91 decodes by base91. // 通过 base91 解码 -func (d decoder) ByBase91() decoder { +func (d Decoder) ByBase91() Decoder { if len(d.src) == 0 { return d } @@ -238,7 +238,7 @@ func (d decoder) ByBase91() decoder { // ByBase100 encodes by base100. // 通过 base100 编码 -func (e encoder) ByBase100() encoder { +func (e Encoder) ByBase100() Encoder { if len(e.src) == 0 { return e } @@ -248,7 +248,7 @@ func (e encoder) ByBase100() encoder { // ByBase100 decodes by base100. // 通过 base100 解码 -func (d decoder) ByBase100() decoder { +func (d Decoder) ByBase100() Decoder { if len(d.src) == 0 { return d } diff --git a/bcrypt.go b/bcrypt.go index a29372e..8cc7d4b 100644 --- a/bcrypt.go +++ b/bcrypt.go @@ -6,7 +6,7 @@ import ( // ByBcrypt signs by bcrypt. // 通过 bcrypt 签名 -func (s signer) ByBcrypt(rounds ...int) signer { +func (s Signer) ByBcrypt(rounds ...int) Signer { if len(s.src) == 0 { return s } @@ -25,7 +25,7 @@ func (s signer) ByBcrypt(rounds ...int) signer { // ByBcrypt verify by bcrypt. // 通过 bcrypt 验签 -func (v verifier) ByBcrypt() verifier { +func (v Verifier) ByBcrypt() Verifier { v.Error = bcrypt.CompareHashAndPassword(interface2bytes(v.sign), v.src) return v } diff --git a/blowfish.go b/blowfish.go new file mode 100644 index 0000000..3876abd --- /dev/null +++ b/blowfish.go @@ -0,0 +1,48 @@ +package dongle + +import ( + "golang.org/x/crypto/blowfish" +) + +// ByBlowfish encrypts by blowfish. +// 通过 blowfish 加密 +func (e Encrypter) ByBlowfish(c *Cipher) Encrypter { + block, err := blowfish.NewCipher(c.key) + if err != nil { + e.Error = invalidBlowfishKeyError() + return e + } + if c.mode != ECB && len(c.iv) != block.BlockSize() { + e.Error = invalidBlowfishIVError() + return e + } + if c.padding == No && len(e.src)%block.BlockSize() != 0 { + e.Error = invalidBlowfishSrcError() + return e + } + e.dst, e.Error = e.encrypt(c, block) + return e +} + +// ByBlowfish decrypts by blowfish. +// 通过 blowfish 解密 +func (d Decrypter) ByBlowfish(c *Cipher) Decrypter { + if d.Error != nil { + return d + } + block, err := blowfish.NewCipher(c.key) + if err != nil { + d.Error = invalidBlowfishKeyError() + return d + } + if c.mode != ECB && len(c.iv) != block.BlockSize() { + d.Error = invalidBlowfishIVError() + return d + } + if (c.mode == CBC || c.padding == No) && len(d.src)%block.BlockSize() != 0 { + d.Error = invalidBlowfishSrcError() + return d + } + d.dst, d.Error = d.decrypt(c, block) + return d +} diff --git a/blowfish_test.go b/blowfish_test.go new file mode 100755 index 0000000..208571e --- /dev/null +++ b/blowfish_test.go @@ -0,0 +1,215 @@ +package dongle + +import ( + "fmt" + "github.com/stretchr/testify/assert" + "testing" +) + +var ( + blowfishKey = "0123456789abcdef" + blowfishIV = "12345678" +) + +var blowfishTests = []struct { + mode cipherMode + padding cipherPadding + input string + toHex string + toBase64 string +}{ + {CBC, PKCS7, "", "", ""}, + {CBC, No, "hello world, go!", "92c3724d720b5998615b123dd9774323", "ksNyTXILWZhhWxI92XdDIw=="}, + {CBC, Zero, "hello world", "92c3724d720b599812a2da1e70f954ff", "ksNyTXILWZgSotoecPlU/w=="}, + {CBC, PKCS5, "hello world", "92c3724d720b59982d21aab9a7bb9f40", "ksNyTXILWZgtIaq5p7ufQA=="}, + {CBC, PKCS7, "hello world", "92c3724d720b59982d21aab9a7bb9f40", "ksNyTXILWZgtIaq5p7ufQA=="}, + {CBC, AnsiX923, "hello world", "92c3724d720b59986113306d58791c7f", "ksNyTXILWZhhEzBtWHkcfw=="}, + {CBC, ISO97971, "hello world", "92c3724d720b599836aa40b4661e1e29", "ksNyTXILWZg2qkC0Zh4eKQ=="}, + + {CFB, PKCS7, "", "", ""}, + {CFB, No, "hello world, go!", "f0ea2f993584f026d070683357c9205c", "8OovmTWE8CbQcGgzV8kgXA=="}, + {CFB, Zero, "hello world", "f0ea2f993584f026d070681f77ae4f7d", "8OovmTWE8CbQcGgfd65PfQ=="}, + {CFB, PKCS5, "hello world", "f0ea2f993584f026d070681a72ab4a78", "8OovmTWE8CbQcGgacqtKeA=="}, + {CFB, PKCS7, "hello world", "f0ea2f993584f026d070681a72ab4a78", "8OovmTWE8CbQcGgacqtKeA=="}, + {CFB, AnsiX923, "hello world", "f0ea2f993584f026d070681f77ae4f78", "8OovmTWE8CbQcGgfd65PeA=="}, + {CFB, ISO97971, "hello world", "f0ea2f993584f026d070689f77ae4f7d", "8OovmTWE8CbQcGifd65PfQ=="}, + + {OFB, PKCS7, "", "", ""}, + {OFB, No, "hello world, go!", "f0ea2f993584f0267e628f1ec7f5d21d", "8OovmTWE8CZ+Yo8ex/XSHQ=="}, + {OFB, Zero, "hello world", "f0ea2f993584f0267e628f32e792bd3c", "8OovmTWE8CZ+Yo8y55K9PA=="}, + {OFB, PKCS5, "hello world", "f0ea2f993584f0267e628f37e297b839", "8OovmTWE8CZ+Yo834pe4OQ=="}, + {OFB, PKCS7, "hello world", "f0ea2f993584f0267e628f37e297b839", "8OovmTWE8CZ+Yo834pe4OQ=="}, + {OFB, AnsiX923, "hello world", "f0ea2f993584f0267e628f32e792bd39", "8OovmTWE8CZ+Yo8y55K9OQ=="}, + {OFB, ISO97971, "hello world", "f0ea2f993584f0267e628fb2e792bd3c", "8OovmTWE8CZ+Yo+y55K9PA=="}, + + {CTR, PKCS7, "", "", ""}, + {CTR, No, "hello world, go!", "f0ea2f993584f026d6f92ffda9d639be", "8OovmTWE8CbW+S/9qdY5vg=="}, + {CTR, Zero, "hello world", "f0ea2f993584f026d6f92fd189b1569f", "8OovmTWE8CbW+S/RibFWnw=="}, + {CTR, PKCS5, "hello world", "f0ea2f993584f026d6f92fd48cb4539a", "8OovmTWE8CbW+S/UjLRTmg=="}, + {CTR, PKCS7, "hello world", "f0ea2f993584f026d6f92fd48cb4539a", "8OovmTWE8CbW+S/UjLRTmg=="}, + {CTR, AnsiX923, "hello world", "f0ea2f993584f026d6f92fd189b1569a", "8OovmTWE8CbW+S/RibFWmg=="}, + {CTR, ISO97971, "hello world", "f0ea2f993584f026d6f92f5189b1569f", "8OovmTWE8CbW+S9RibFWnw=="}, + + {ECB, PKCS7, "", "", ""}, + {ECB, No, "hello world, go!", "954ddb4b65c05c90112006edaeda25f5", "lU3bS2XAXJARIAbtrtol9Q=="}, + {ECB, Zero, "hello world", "954ddb4b65c05c90c8cb0c6bbb3ec912", "lU3bS2XAXJDIywxruz7JEg=="}, + {ECB, PKCS5, "hello world", "954ddb4b65c05c9022457a6f07c5859c", "lU3bS2XAXJAiRXpvB8WFnA=="}, + {ECB, PKCS7, "hello world", "954ddb4b65c05c9022457a6f07c5859c", "lU3bS2XAXJAiRXpvB8WFnA=="}, + {ECB, AnsiX923, "hello world", "954ddb4b65c05c90b4c296978984f345", "lU3bS2XAXJC0wpaXiYTzRQ=="}, + {ECB, ISO97971, "hello world", "954ddb4b65c05c907227aaa09f2e4ddb", "lU3bS2XAXJByJ6qgny5N2w=="}, +} + +func TestBlowfish_Encrypt_String(t *testing.T) { + for index, test := range blowfishTests { + raw := Decode.FromString(test.toHex).ByHex().ToString() + e := Encrypt.FromString(test.input).ByBlowfish(getCipher(test.mode, test.padding, blowfishKey, blowfishIV)) + + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_raw_test_%d", index), func(t *testing.T) { + assert.Nil(t, e.Error) + assert.Equal(t, raw, e.ToRawString()) + }) + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_hex_test_%d", index), func(t *testing.T) { + assert.Nil(t, e.Error) + assert.Equal(t, test.toHex, e.ToHexString()) + }) + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_base64_test_%d", index), func(t *testing.T) { + assert.Nil(t, e.Error) + assert.Equal(t, test.toBase64, e.ToBase64String()) + }) + } +} + +func TestBlowfish_Decrypt_String(t *testing.T) { + for index, test := range blowfishTests { + raw := Decode.FromString(test.toHex).ByHex().ToString() + e := Decrypt.FromRawString(raw).ByBlowfish(getCipher(test.mode, test.padding, blowfishKey, blowfishIV)) + + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_raw_test_%d", index), func(t *testing.T) { + assert.Nil(t, e.Error) + assert.Equal(t, test.input, e.ToString()) + assert.Equal(t, test.input, fmt.Sprintf("%s", e)) + }) + } + + for index, test := range blowfishTests { + e := Decrypt.FromHexString(test.toHex).ByBlowfish(getCipher(test.mode, test.padding, blowfishKey, blowfishIV)) + + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_hex_test_%d", index), func(t *testing.T) { + assert.Nil(t, e.Error) + assert.Equal(t, test.input, e.ToString()) + assert.Equal(t, test.input, fmt.Sprintf("%s", e)) + }) + } + + for index, test := range blowfishTests { + e := Decrypt.FromBase64String(test.toBase64).ByBlowfish(getCipher(test.mode, test.padding, blowfishKey, blowfishIV)) + + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_base64_test_%d", index), func(t *testing.T) { + assert.Nil(t, e.Error) + assert.Equal(t, test.input, e.ToString()) + assert.Equal(t, test.input, fmt.Sprintf("%s", e)) + }) + } +} + +func TestBlowfish_Encrypt_Bytes(t *testing.T) { + for index, test := range blowfishTests { + raw := Decode.FromBytes([]byte(test.toHex)).ByHex().ToBytes() + e := Encrypt.FromBytes([]byte(test.input)).ByBlowfish(getCipher(test.mode, test.padding, []byte(blowfishKey), []byte(blowfishIV))) + + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_raw_test_%d", index), func(t *testing.T) { + assert.Nil(t, e.Error) + assert.Equal(t, raw, e.ToRawBytes()) + }) + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_hex_test_%d", index), func(t *testing.T) { + assert.Nil(t, e.Error) + assert.Equal(t, []byte(test.toHex), e.ToHexBytes()) + }) + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_base64_test_%d", index), func(t *testing.T) { + assert.Nil(t, e.Error) + assert.Equal(t, []byte(test.toBase64), e.ToBase64Bytes()) + }) + } +} + +func TestBlowfish_Decrypt_Bytes(t *testing.T) { + for index, test := range blowfishTests { + raw := Decode.FromBytes([]byte(test.toHex)).ByHex().ToBytes() + e := Decrypt.FromRawBytes(raw).ByBlowfish(getCipher(test.mode, test.padding, []byte(blowfishKey), []byte(blowfishIV))) + + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_raw_test_%d", index), func(t *testing.T) { + assert.Nil(t, e.Error) + assert.Equal(t, []byte(test.input), e.ToBytes()) + }) + } + + for index, test := range blowfishTests { + e := Decrypt.FromHexBytes([]byte(test.toHex)).ByBlowfish(getCipher(test.mode, test.padding, []byte(blowfishKey), []byte(blowfishIV))) + + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_hex_test_%d", index), func(t *testing.T) { + assert.Nil(t, e.Error) + assert.Equal(t, []byte(test.input), e.ToBytes()) + }) + } + + for index, test := range blowfishTests { + e := Decrypt.FromBase64Bytes([]byte(test.toBase64)).ByBlowfish(getCipher(test.mode, test.padding, []byte(blowfishKey), []byte(blowfishIV))) + + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_base64_test_%d", index), func(t *testing.T) { + assert.Nil(t, e.Error) + assert.Equal(t, []byte(test.input), e.ToBytes()) + }) + } +} + +func TestBlowfish_Key_Error(t *testing.T) { + e := Encrypt.FromString("hello world").ByBlowfish(getCipher(CBC, PKCS7, "", blowfishIV)) + assert.Equal(t, invalidBlowfishKeyError(), e.Error) + + d := Decrypt.FromHexString("c1e9b4529aac9793010f4677f6358efe").ByBlowfish(getCipher(CBC, PKCS7, "", blowfishIV)) + assert.Equal(t, invalidBlowfishKeyError(), d.Error) +} + +func TestBlowfish_IV_Error(t *testing.T) { + e := Encrypt.FromString("hello world").ByBlowfish(getCipher(OFB, PKCS7, blowfishKey, "xxxx")) + assert.Equal(t, invalidBlowfishIVError(), e.Error) + + d := Decrypt.FromHexString("c1e9b4529aac9793010f4677f6358efec1e9b4529aac9793010f4677f6358efe").ByBlowfish(getCipher(CBC, PKCS7, blowfishKey, "xxxx")) + assert.Equal(t, invalidBlowfishIVError(), d.Error) +} + +func TestBlowfish_Mode_Error(t *testing.T) { + e := Encrypt.FromString("hello world").ByBlowfish(getCipher("xxxx", PKCS7, blowfishKey, blowfishIV)) + assert.Equal(t, invalidModeError("xxxx"), e.Error) + + d := Decrypt.FromHexString("c1e9b4529aac9793010f4677f6358efe").ByBlowfish(getCipher("xxxx", PKCS7, blowfishKey, blowfishIV)) + assert.Equal(t, invalidModeError("xxxx"), d.Error) +} + +func TestBlowfish_Padding_Error(t *testing.T) { + e := Encrypt.FromString("hello world").ByBlowfish(getCipher(CFB, "xxxx", blowfishKey, blowfishIV)) + assert.Equal(t, invalidPaddingError("xxxx"), e.Error) + + d := Decrypt.FromHexString("c1e9b4529aac9793010f4677f6358efe").ByBlowfish(getCipher(CBC, "xxxx", blowfishKey, blowfishIV)) + assert.Equal(t, invalidPaddingError("xxxx"), d.Error) +} + +func TestBlowfish_Src_Error(t *testing.T) { + e := Encrypt.FromString("hello world").ByBlowfish(getCipher(CFB, No, blowfishKey, blowfishIV)) + assert.Equal(t, invalidBlowfishSrcError(), e.Error) + + d := Decrypt.FromHexString("68656c6c6f20776f726c64").ByBlowfish(getCipher(CBC, No, blowfishKey, blowfishIV)) + assert.Equal(t, invalidBlowfishSrcError(), d.Error) +} + +func TestBlowfish_Decoding_Error(t *testing.T) { + d1 := Decrypt.FromHexString("xxxx").ByBlowfish(getCipher(CTR, Zero, blowfishKey, blowfishIV)) + assert.Equal(t, invalidDecodingError("hex"), d1.Error) + d2 := Decrypt.FromHexBytes([]byte("xxxx")).ByBlowfish(getCipher(CTR, Zero, []byte(blowfishKey), []byte(blowfishIV))) + assert.Equal(t, invalidDecodingError("hex"), d2.Error) + + d3 := Decrypt.FromBase64String("xxxxxx").ByBlowfish(getCipher(CFB, PKCS7, blowfishKey, blowfishIV)) + assert.Equal(t, invalidDecodingError("base64"), d3.Error) + d4 := Decrypt.FromBase64Bytes([]byte("xxxxxx")).ByBlowfish(getCipher(CFB, PKCS7, []byte(blowfishKey), []byte(blowfishIV))) + assert.Equal(t, invalidDecodingError("base64"), d4.Error) +} diff --git a/cipher.go b/cipher.go index 4d6b93d..c19dc74 100644 --- a/cipher.go +++ b/cipher.go @@ -26,10 +26,12 @@ type cipherPadding string // cipher padding constants. // 填充模式常量 const ( - No cipherPadding = "no" - Zero cipherPadding = "zero" - PKCS5 cipherPadding = "pkcs5" - PKCS7 cipherPadding = "pkcs7" + No cipherPadding = "no" + Zero cipherPadding = "zero" + PKCS5 cipherPadding = "pkcs5" + PKCS7 cipherPadding = "pkcs7" + AnsiX923 cipherPadding = "ansi-x-923" + ISO97971 cipherPadding = "iso9797-1" ) // Cipher defines a Cipher struct. @@ -85,7 +87,37 @@ func (c *Cipher) ZeroPadding(src []byte, blockSize int) []byte { // ZeroUnPadding removes padding with Zero mode. // 移除 0 填充 func (c *Cipher) ZeroUnPadding(src []byte) []byte { - return bytes.TrimRight(src, string([]byte{0})) + return bytes.TrimFunc(src, func(r rune) bool { + return r == rune(0) + }) +} + +// ISO97971Padding padding with ISO/IEC 9797-1 mode. +// 进行 ISO/IEC 9797-1 填充 +func (c *Cipher) ISO97971Padding(src []byte, blockSize int) []byte { + return c.ZeroPadding(append(src, 0x80), blockSize) +} + +// ISO97971UnPadding removes padding with ISO/IEC 9797-1 mode. +// 移除 ISO/IEC 9797-1 填充 +func (c *Cipher) ISO97971UnPadding(src []byte) []byte { + dst := c.ZeroUnPadding(src) + return dst[:len(dst)-1] +} + +// AnsiX923Padding padding with ANSI X.923 mode. +// 进行 ANSI X.923 填充 +func (c *Cipher) AnsiX923Padding(src []byte, blockSize int) []byte { + paddingSize := blockSize - len(src)%blockSize + paddingText := append(bytes.Repeat([]byte{byte(0)}, paddingSize-1), byte(paddingSize)) + return append(src, paddingText...) +} + +// AnsiX923UnPadding removes padding with ANSI X.923 mode. +// 移除 ANSI X.923 填充 +func (c *Cipher) AnsiX923UnPadding(src []byte) []byte { + n := len(src) - int(src[len(src)-1]) + return src[0:n] } // PKCS5Padding padding with PKCS5 mode. @@ -111,15 +143,15 @@ func (c *Cipher) PKCS7Padding(src []byte, blockSize int) []byte { // PKCS7UnPadding removes padding with PKCS7 mode. // 移除 PKCS7 填充 func (c *Cipher) PKCS7UnPadding(src []byte) []byte { - trim := len(src) - int(src[len(src)-1]) - return src[:trim] + n := len(src) - int(src[len(src)-1]) + return src[0:n] } // NewCBCEncrypter encrypts with CBC mode. // CBC 模式加密 func (c *Cipher) NewCBCEncrypter(src []byte, block cipher.Block) (dst []byte) { dst = make([]byte, len(src)) - cipher.NewCBCEncrypter(block, c.iv[:block.BlockSize()]).CryptBlocks(dst, src) + cipher.NewCBCEncrypter(block, c.iv).CryptBlocks(dst, src) return } @@ -127,7 +159,7 @@ func (c *Cipher) NewCBCEncrypter(src []byte, block cipher.Block) (dst []byte) { // CBC 模式解密 func (c *Cipher) NewCBCDecrypter(src []byte, block cipher.Block) (dst []byte) { dst = make([]byte, len(src)) - cipher.NewCBCDecrypter(block, c.iv[:block.BlockSize()]).CryptBlocks(dst, src) + cipher.NewCBCDecrypter(block, c.iv).CryptBlocks(dst, src) return } @@ -135,7 +167,7 @@ func (c *Cipher) NewCBCDecrypter(src []byte, block cipher.Block) (dst []byte) { // CFB 模式加密 func (c *Cipher) NewCFBEncrypter(src []byte, block cipher.Block) (dst []byte) { dst = make([]byte, len(src)) - cipher.NewCFBEncrypter(block, c.iv[:block.BlockSize()]).XORKeyStream(dst, src) + cipher.NewCFBEncrypter(block, c.iv).XORKeyStream(dst, src) return } @@ -143,7 +175,7 @@ func (c *Cipher) NewCFBEncrypter(src []byte, block cipher.Block) (dst []byte) { // CFB 模式解密 func (c *Cipher) NewCFBDecrypter(src []byte, block cipher.Block) (dst []byte) { dst = make([]byte, len(src)) - cipher.NewCFBDecrypter(block, c.iv[:block.BlockSize()]).XORKeyStream(dst, src) + cipher.NewCFBDecrypter(block, c.iv).XORKeyStream(dst, src) return } @@ -151,7 +183,7 @@ func (c *Cipher) NewCFBDecrypter(src []byte, block cipher.Block) (dst []byte) { // CTR 模式加密 func (c *Cipher) NewCTREncrypter(src []byte, block cipher.Block) (dst []byte) { dst = make([]byte, len(src)) - cipher.NewCTR(block, c.iv[:block.BlockSize()]).XORKeyStream(dst, src) + cipher.NewCTR(block, c.iv).XORKeyStream(dst, src) return } @@ -159,7 +191,7 @@ func (c *Cipher) NewCTREncrypter(src []byte, block cipher.Block) (dst []byte) { // CTR 模式解密 func (c *Cipher) NewCTRDecrypter(src []byte, block cipher.Block) (dst []byte) { dst = make([]byte, len(src)) - cipher.NewCTR(block, c.iv[:block.BlockSize()]).XORKeyStream(dst, src) + cipher.NewCTR(block, c.iv).XORKeyStream(dst, src) return } @@ -180,11 +212,11 @@ func (c *Cipher) NewECBEncrypter(src []byte, block cipher.Block) (dst []byte) { // ECB 模式解密 func (c *Cipher) NewECBDecrypter(src []byte, block cipher.Block) (dst []byte) { dst = make([]byte, len(src)) - decrypted, size := dst, block.BlockSize() + decrypted, blockSize := dst, block.BlockSize() for len(src) > 0 { - block.Decrypt(decrypted, src[:size]) - src = src[size:] - decrypted = decrypted[size:] + block.Decrypt(decrypted, src[:blockSize]) + src = src[blockSize:] + decrypted = decrypted[blockSize:] } return } @@ -204,3 +236,28 @@ func (c *Cipher) NewOFBDecrypter(src []byte, block cipher.Block) (dst []byte) { cipher.NewOFB(block, c.iv[:block.BlockSize()]).XORKeyStream(dst, src) return } + +// whether is a supported padding +// 判断是否是支持的填充模式 +func (padding cipherPadding) isSupported() bool { + paddings := []cipherPadding{ + No, Zero, PKCS5, PKCS7, AnsiX923, ISO97971, + } + for _, val := range paddings { + if val == padding { + return true + } + } + return false +} + +// gets Cipher instance. +// 获取 Cipher 对象 +func getCipher(mode cipherMode, padding cipherPadding, key, iv interface{}) (cipher *Cipher) { + cipher = NewCipher() + cipher.SetMode(mode) + cipher.SetPadding(padding) + cipher.SetKey(key) + cipher.SetIV(iv) + return +} diff --git a/decode.go b/decoder.go similarity index 50% rename from decode.go rename to decoder.go index be61a41..4957dd5 100644 --- a/decode.go +++ b/decoder.go @@ -1,46 +1,46 @@ package dongle -// defines a decoder struct. -// 定义 decoder 结构体 -type decoder struct { +// Decoder defines Decoder struct. +// 定义 Decoder 结构体 +type Decoder struct { dongle } -// NewDecoder returns a new decoder instance. -// 初始化 decoder 结构体 -func NewDecoder() decoder { - return decoder{} +// newDecoder returns a new Decoder instance. +// 初始化 Decoder 结构体 +func newDecoder() Decoder { + return Decoder{} } // FromString decodes from string. // 对字符串进行解密 -func (d decoder) FromString(s string) decoder { +func (d Decoder) FromString(s string) Decoder { d.src = string2bytes(s) return d } // FromBytes decodes from byte slice. // 对字节切片进行解密 -func (d decoder) FromBytes(b []byte) decoder { +func (d Decoder) FromBytes(b []byte) Decoder { d.src = b return d } -// String implements the interface Stringer for decoder struct. +// String implements Stringer interface for Decoder struct. // 实现 Stringer 接口 -func (d decoder) String() string { +func (d Decoder) String() string { return d.ToString() } // ToString outputs as string. // 输出字符串 -func (d decoder) ToString() string { +func (d Decoder) ToString() string { return bytes2string(d.dst) } // ToBytes outputs as byte slice. // 输出字节切片 -func (d decoder) ToBytes() []byte { +func (d Decoder) ToBytes() []byte { if len(d.dst) == 0 { return []byte("") } diff --git a/decrypt.go b/decrypter.go similarity index 71% rename from decrypt.go rename to decrypter.go index 9e39880..078c225 100644 --- a/decrypt.go +++ b/decrypter.go @@ -4,28 +4,28 @@ import ( "crypto/cipher" ) -// decrypter defines decrypter struct -// 定义 decrypter 结构体 -type decrypter struct { +// Decrypter defines Decrypter struct. +// 定义 Decrypter 结构体 +type Decrypter struct { dongle } -// NewDecrypter returns a new decrypter instance. -// 初始化 decrypter 结构体 -func NewDecrypter() decrypter { - return decrypter{} +// newDecrypter returns a new Decrypter instance. +// 初始化 Decrypter 结构体 +func newDecrypter() Decrypter { + return Decrypter{} } // FromRawString decrypts from raw string without encoding. // 对未经编码的原始字符串进行解密 -func (d decrypter) FromRawString(s string) decrypter { +func (d Decrypter) FromRawString(s string) Decrypter { d.src = string2bytes(s) return d } // FromHexString decrypts from string with hex encoding. // 对经过 hex 编码的字符串进行解密 -func (d decrypter) FromHexString(s string) decrypter { +func (d Decrypter) FromHexString(s string) Decrypter { decode := Decode.FromString(s).ByHex() if decode.Error != nil { d.Error = invalidDecodingError("hex") @@ -37,7 +37,7 @@ func (d decrypter) FromHexString(s string) decrypter { // FromBase64String decrypts from string with base64 encoding. // 对经过 base64 编码的字符串进行解密 -func (d decrypter) FromBase64String(s string) decrypter { +func (d Decrypter) FromBase64String(s string) Decrypter { decode := Decode.FromString(s).ByBase64() if decode.Error != nil { d.Error = invalidDecodingError("base64") @@ -49,14 +49,14 @@ func (d decrypter) FromBase64String(s string) decrypter { // FromRawBytes decrypts from raw byte slice without encoding. // 对未经编码的原始字节切片进行解密 -func (d decrypter) FromRawBytes(b []byte) decrypter { +func (d Decrypter) FromRawBytes(b []byte) Decrypter { d.src = b return d } // FromHexBytes decrypts from byte slice with hex encoding. // 对经过 hex 编码的字节切片进行解密 -func (d decrypter) FromHexBytes(b []byte) decrypter { +func (d Decrypter) FromHexBytes(b []byte) Decrypter { decode := Decode.FromBytes(b).ByHex() if decode.Error != nil { d.Error = invalidDecodingError("hex") @@ -68,7 +68,7 @@ func (d decrypter) FromHexBytes(b []byte) decrypter { // FromBase64Bytes decrypts from byte slice with base64 encoding. // 对经过 base64 编码的字节切片进行解密 -func (d decrypter) FromBase64Bytes(b []byte) decrypter { +func (d Decrypter) FromBase64Bytes(b []byte) Decrypter { decode := Decode.FromBytes(b).ByBase64() if decode.Error != nil { d.Error = invalidDecodingError("base64") @@ -78,21 +78,21 @@ func (d decrypter) FromBase64Bytes(b []byte) decrypter { return d } -// String implements the interface Stringer for decrypter struct. +// String implements Stringer interface for Decrypter struct. // 实现 Stringer 接口 -func (d decrypter) String() string { +func (d Decrypter) String() string { return d.ToString() } // ToString outputs as string. // 输出字符串 -func (d decrypter) ToString() string { +func (d Decrypter) ToString() string { return bytes2string(d.dst) } // ToBytes outputs as byte slice. // 输出字节切片 -func (d decrypter) ToBytes() []byte { +func (d Decrypter) ToBytes() []byte { if len(d.dst) == 0 { return []byte("") } @@ -101,12 +101,12 @@ func (d decrypter) ToBytes() []byte { // decrypts with given mode and padding. // 根据指定的分组模式和填充模式进行解密 -func (d decrypter) decrypt(c *Cipher, b cipher.Block) (dst []byte, err error) { +func (d Decrypter) decrypt(c *Cipher, b cipher.Block) (dst []byte, err error) { src, mode, padding := d.src, c.mode, c.padding if len(src) == 0 { return nil, nil } - if padding != No && padding != Zero && padding != PKCS5 && padding != PKCS7 { + if !padding.isSupported() { return nil, invalidPaddingError(padding) } @@ -132,6 +132,10 @@ func (d decrypter) decrypt(c *Cipher, b cipher.Block) (dst []byte, err error) { return c.PKCS5UnPadding(src), nil case PKCS7: return c.PKCS7UnPadding(src), nil + case AnsiX923: + return c.AnsiX923UnPadding(src), nil + case ISO97971: + return c.ISO97971UnPadding(src), nil } return src, nil } diff --git a/des.go b/des.go index 44f03a8..6871ab1 100644 --- a/des.go +++ b/des.go @@ -6,7 +6,7 @@ import ( // ByDes encrypts by des. // 通过 des 加密 -func (e encrypter) ByDes(c *Cipher) encrypter { +func (e Encrypter) ByDes(c *Cipher) Encrypter { block, err := des.NewCipher(c.key) if err != nil { e.Error = invalidDesKeyError() @@ -26,7 +26,7 @@ func (e encrypter) ByDes(c *Cipher) encrypter { // ByDes decrypts by des. // 通过 des 解密 -func (d decrypter) ByDes(c *Cipher) decrypter { +func (d Decrypter) ByDes(c *Cipher) Decrypter { if d.Error != nil { return d } diff --git a/des_test.go b/des_test.go index 2ce80f2..a1355c8 100755 --- a/des_test.go +++ b/des_test.go @@ -18,35 +18,45 @@ var desTests = []struct { toHex string toBase64 string }{ - {CBC, "", "", "", ""}, + {CBC, PKCS7, "", "", ""}, {CBC, No, "hello world, go!", "0b2a92e81fb49ce1b161ab1a2e35d7ce", "CyqS6B+0nOGxYasaLjXXzg=="}, {CBC, Zero, "hello world", "0b2a92e81fb49ce1e02ecfa986df2ec8", "CyqS6B+0nOHgLs+pht8uyA=="}, {CBC, PKCS5, "hello world", "0b2a92e81fb49ce1a43266aacaea7b81", "CyqS6B+0nOGkMmaqyup7gQ=="}, {CBC, PKCS7, "hello world", "0b2a92e81fb49ce1a43266aacaea7b81", "CyqS6B+0nOGkMmaqyup7gQ=="}, + {CBC, AnsiX923, "hello world", "0b2a92e81fb49ce1c450d98b1e527b4a", "CyqS6B+0nOHEUNmLHlJ7Sg=="}, + {CBC, ISO97971, "hello world", "0b2a92e81fb49ce1cd126e4be2f294cd", "CyqS6B+0nOHNEm5L4vKUzQ=="}, - {CFB, "", "", "", ""}, + {CFB, PKCS7, "", "", ""}, {CFB, No, "hello world, go!", "feb56ee417f5fbe61a4e5700b93c340b", "/rVu5Bf1++YaTlcAuTw0Cw=="}, {CFB, Zero, "hello world", "feb56ee417f5fbe61a4e572c995b5b2a", "/rVu5Bf1++YaTlcsmVtbKg=="}, {CFB, PKCS5, "hello world", "feb56ee417f5fbe61a4e57299c5e5e2f", "/rVu5Bf1++YaTlcpnF5eLw=="}, {CFB, PKCS7, "hello world", "feb56ee417f5fbe61a4e57299c5e5e2f", "/rVu5Bf1++YaTlcpnF5eLw=="}, + {CFB, AnsiX923, "hello world", "feb56ee417f5fbe61a4e572c995b5b2f", "/rVu5Bf1++YaTlcsmVtbLw=="}, + {CFB, ISO97971, "hello world", "feb56ee417f5fbe61a4e57ac995b5b2a", "/rVu5Bf1++YaTlesmVtbKg=="}, - {OFB, "", "", "", ""}, + {OFB, PKCS7, "", "", ""}, {OFB, No, "hello world, go!", "feb56ee417f5fbe69b19fcf309087d8b", "/rVu5Bf1++abGfzzCQh9iw=="}, {OFB, Zero, "hello world", "feb56ee417f5fbe69b19fcdf296f12aa", "/rVu5Bf1++abGfzfKW8Sqg=="}, {OFB, PKCS5, "hello world", "feb56ee417f5fbe69b19fcda2c6a17af", "/rVu5Bf1++abGfzaLGoXrw=="}, {OFB, PKCS7, "hello world", "feb56ee417f5fbe69b19fcda2c6a17af", "/rVu5Bf1++abGfzaLGoXrw=="}, + {OFB, AnsiX923, "hello world", "feb56ee417f5fbe69b19fcdf296f12af", "/rVu5Bf1++abGfzfKW8Srw=="}, + {OFB, ISO97971, "hello world", "feb56ee417f5fbe69b19fc5f296f12aa", "/rVu5Bf1++abGfxfKW8Sqg=="}, - {CTR, "", "", "", ""}, + {CTR, PKCS7, "", "", ""}, {CTR, No, "hello world, go!", "feb56ee417f5fbe6337e8b3af91e9929", "/rVu5Bf1++Yzfos6+R6ZKQ=="}, {CTR, Zero, "hello world", "feb56ee417f5fbe6337e8b16d979f608", "/rVu5Bf1++YzfosW2Xn2CA=="}, {CTR, PKCS5, "hello world", "feb56ee417f5fbe6337e8b13dc7cf30d", "/rVu5Bf1++YzfosT3HzzDQ=="}, {CTR, PKCS7, "hello world", "feb56ee417f5fbe6337e8b13dc7cf30d", "/rVu5Bf1++YzfosT3HzzDQ=="}, + {CTR, AnsiX923, "hello world", "feb56ee417f5fbe6337e8b16d979f60d", "/rVu5Bf1++YzfosW2Xn2DQ=="}, + {CTR, ISO97971, "hello world", "feb56ee417f5fbe6337e8b96d979f608", "/rVu5Bf1++YzfouW2Xn2CA=="}, - {ECB, "", "", "", ""}, + {ECB, PKCS7, "", "", ""}, {ECB, No, "hello world, go!", "28dba02eb5f6dd47e5a66298af31d4ca", "KNugLrX23UflpmKYrzHUyg=="}, {ECB, Zero, "hello world", "28dba02eb5f6dd476042daebfa59687a", "KNugLrX23UdgQtrr+lloeg=="}, {ECB, PKCS5, "hello world", "28dba02eb5f6dd475d82e3681c83bb77", "KNugLrX23UddguNoHIO7dw=="}, {ECB, PKCS7, "hello world", "28dba02eb5f6dd475d82e3681c83bb77", "KNugLrX23UddguNoHIO7dw=="}, + {ECB, AnsiX923, "hello world", "28dba02eb5f6dd47d33696d839c770b2", "KNugLrX23UfTNpbYOcdwsg=="}, + {ECB, ISO97971, "hello world", "28dba02eb5f6dd4706b5c56593dcbe2c", "KNugLrX23UcGtcVlk9y+LA=="}, } func TestDes_Encrypt_String(t *testing.T) { @@ -54,15 +64,15 @@ func TestDes_Encrypt_String(t *testing.T) { raw := Decode.FromString(test.toHex).ByHex().ToString() e := Encrypt.FromString(test.input).ByDes(getCipher(test.mode, test.padding, desKey, desIV)) - t.Run(fmt.Sprintf(string(test.mode)+"_raw_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_raw_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, raw, e.ToRawString()) }) - t.Run(fmt.Sprintf(string(test.mode)+"_hex_hex_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_hex_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, test.toHex, e.ToHexString()) }) - t.Run(fmt.Sprintf(string(test.mode)+"_base64_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_base64_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, test.toBase64, e.ToBase64String()) }) @@ -74,7 +84,7 @@ func TestDes_Decrypt_String(t *testing.T) { raw := Decode.FromString(test.toHex).ByHex().ToString() e := Decrypt.FromRawString(raw).ByDes(getCipher(test.mode, test.padding, desKey, desIV)) - t.Run(fmt.Sprintf(string(test.mode)+"_raw_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_raw_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, test.input, e.ToString()) assert.Equal(t, test.input, fmt.Sprintf("%s", e)) @@ -84,7 +94,7 @@ func TestDes_Decrypt_String(t *testing.T) { for index, test := range desTests { e := Decrypt.FromHexString(test.toHex).ByDes(getCipher(test.mode, test.padding, desKey, desIV)) - t.Run(fmt.Sprintf(string(test.mode)+"_hex_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_hex_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, test.input, e.ToString()) assert.Equal(t, test.input, fmt.Sprintf("%s", e)) @@ -94,7 +104,7 @@ func TestDes_Decrypt_String(t *testing.T) { for index, test := range desTests { e := Decrypt.FromBase64String(test.toBase64).ByDes(getCipher(test.mode, test.padding, desKey, desIV)) - t.Run(fmt.Sprintf(string(test.mode)+"_base64_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_base64_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, test.input, e.ToString()) assert.Equal(t, test.input, fmt.Sprintf("%s", e)) @@ -107,15 +117,15 @@ func TestDes_Encrypt_Bytes(t *testing.T) { raw := Decode.FromBytes([]byte(test.toHex)).ByHex().ToBytes() e := Encrypt.FromBytes([]byte(test.input)).ByDes(getCipher(test.mode, test.padding, []byte(desKey), []byte(desIV))) - t.Run(fmt.Sprintf(string(test.mode)+"_raw_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_raw_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, raw, e.ToRawBytes()) }) - t.Run(fmt.Sprintf(string(test.mode)+"_hex_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_hex_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, []byte(test.toHex), e.ToHexBytes()) }) - t.Run(fmt.Sprintf(string(test.mode)+"_base64_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_base64_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, []byte(test.toBase64), e.ToBase64Bytes()) }) @@ -127,7 +137,7 @@ func TestDes_Decrypt_Bytes(t *testing.T) { raw := Decode.FromBytes([]byte(test.toHex)).ByHex().ToBytes() e := Decrypt.FromRawBytes(raw).ByDes(getCipher(test.mode, test.padding, []byte(desKey), []byte(desIV))) - t.Run(fmt.Sprintf(string(test.mode)+"_raw_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_raw_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, []byte(test.input), e.ToBytes()) }) @@ -136,7 +146,7 @@ func TestDes_Decrypt_Bytes(t *testing.T) { for index, test := range desTests { e := Decrypt.FromHexBytes([]byte(test.toHex)).ByDes(getCipher(test.mode, test.padding, []byte(desKey), []byte(desIV))) - t.Run(fmt.Sprintf(string(test.mode)+"_hex_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_hex_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, []byte(test.input), e.ToBytes()) }) @@ -145,7 +155,7 @@ func TestDes_Decrypt_Bytes(t *testing.T) { for index, test := range desTests { e := Decrypt.FromBase64Bytes([]byte(test.toBase64)).ByDes(getCipher(test.mode, test.padding, []byte(desKey), []byte(desIV))) - t.Run(fmt.Sprintf(string(test.mode)+"_base64_test_%d", index), func(t *testing.T) { + t.Run(fmt.Sprintf(string(test.mode)+"_"+string(test.padding)+"_base64_test_%d", index), func(t *testing.T) { assert.Nil(t, e.Error) assert.Equal(t, []byte(test.input), e.ToBytes()) }) diff --git a/dongle.go b/dongle.go index b0d1cad..34db9bb 100644 --- a/dongle.go +++ b/dongle.go @@ -1,11 +1,11 @@ // @Package dongle -// @Description a simple, semantic and developer-friendly golang package for encoding&decoding and encryption&decryption +// @Description a simple, semantic and developer-friendly golang package for encoding&decoding, encryption&decryption and signature&verification // @Page github.com/golang-module/dongle // @Developer gouguoyin -// @Blog www.gouguoyin.cn -// @Email contact@gouguoyin.cn +// @Blog www.gouguoyin.com +// @Email contact@gouguoyin.com -// Package dongle is a simple, semantic and developer-friendly golang package for encoding&decoding and encryption&decryption. +// Package dongle is a simple, semantic and developer-friendly golang package for encoding&decoding, encryption&decryption and signature&verification. package dongle import ( @@ -14,7 +14,7 @@ import ( // Version current version // 当前版本号 -const Version = "0.2.1" +const Version = "0.2.2" // dongle defines a dongle struct. // 定义 dongle 结构体 @@ -25,24 +25,24 @@ type dongle struct { } var ( - // Encode returns a new encoder instance + // Encode returns a new Encoder instance // 返回 encoder 实例 - Encode = NewEncoder() - // Decode returns a new decoder instance + Encode = newEncoder() + // Decode returns a new Decoder instance // 返回 decoder 实例 - Decode = NewDecoder() - // Encrypt returns a new encrypter instance + Decode = newDecoder() + // Encrypt returns a new Encrypter instance // 返回 encrypter 实例 - Encrypt = NewEncrypter() - // Decrypt returns a new decrypter instance + Encrypt = newEncrypter() + // Decrypt returns a new Decrypter instance // 返回 decrypter 实例 - Decrypt = NewDecrypter() - // Sign returns a new signer instance + Decrypt = newDecrypter() + // Sign returns a new Signer instance // 返回 signer 实例 - Sign = NewSigner() - // Verify returns a new verifier instance + Sign = newSigner() + // Verify returns a new Verifier instance // 返回 verifier 实例 - Verify = NewVerifier() + Verify = newVerifier() ) // converts string to byte slice without a memory allocation. @@ -79,14 +79,3 @@ func interface2bytes(i interface{}) (b []byte) { } return } - -// gets Cipher instance. -// 获取 Cipher 对象 -func getCipher(mode cipherMode, padding cipherPadding, key, iv interface{}) (cipher *Cipher) { - cipher = NewCipher() - cipher.SetMode(mode) - cipher.SetPadding(padding) - cipher.SetKey(key) - cipher.SetIV(iv) - return -} diff --git a/ed25519.go b/ed25519.go index dfced3c..572f395 100644 --- a/ed25519.go +++ b/ed25519.go @@ -9,7 +9,7 @@ import ( type encodingMode string // encoding mode constants -// 编码模式常量 +// 编码模式枚举值 const ( Raw encodingMode = "raw" Hex encodingMode = "hex" @@ -18,11 +18,11 @@ const ( // ByEd25519 signs by ed25519. // 通过 ed25519 私钥签名 -func (s signer) ByEd25519(privateKey interface{}, mode encodingMode) signer { +func (s Signer) ByEd25519(privateKey interface{}, mode encodingMode) Signer { if len(s.src) == 0 || s.Error != nil { return s } - pri, err := getDecodedKey(interface2bytes(privateKey), mode) + pri, err := mode.getDecodedKey(interface2bytes(privateKey)) if err != nil { s.Error = err return s @@ -37,11 +37,11 @@ func (s signer) ByEd25519(privateKey interface{}, mode encodingMode) signer { // ByEd25519 verify by ed25519. // 通过 ed25519 公钥验签 -func (v verifier) ByEd25519(publicKey interface{}, mode encodingMode) verifier { +func (v Verifier) ByEd25519(publicKey interface{}, mode encodingMode) Verifier { if len(v.src) == 0 || v.Error != nil { return v } - pub, err := getDecodedKey(interface2bytes(publicKey), mode) + pub, err := mode.getDecodedKey(interface2bytes(publicKey)) if err != nil { v.Error = err return v @@ -58,9 +58,9 @@ func (v verifier) ByEd25519(publicKey interface{}, mode encodingMode) verifier { } // gets the decoded key -// 获取解码的 key -func getDecodedKey(key []byte, mode encodingMode) (dst []byte, err error) { - var decode decoder +// 获取经过解码的 密钥 +func (mode encodingMode) getDecodedKey(key []byte) (dst []byte, err error) { + var decode Decoder switch mode { case Raw: dst = key diff --git a/encode.go b/encoder.go similarity index 53% rename from encode.go rename to encoder.go index fb9637e..f7bab79 100644 --- a/encode.go +++ b/encoder.go @@ -1,46 +1,46 @@ package dongle -// defines a encoder struct. -// 定义 encoder 结构体 -type encoder struct { +// Encoder defines Encoder struct. +// 定义 Encoder 结构体 +type Encoder struct { dongle } -// NewEncoder returns a new encoder instance. +// newEncoder returns a new Encoder instance. // 初始化 encoder 结构体 -func NewEncoder() encoder { - return encoder{} +func newEncoder() Encoder { + return Encoder{} } // FromString encodes from string. // 对字符串进行编码 -func (e encoder) FromString(s string) encoder { +func (e Encoder) FromString(s string) Encoder { e.src = string2bytes(s) return e } // FromBytes encodes from byte slice. // 对字节切片进行编码 -func (e encoder) FromBytes(b []byte) encoder { +func (e Encoder) FromBytes(b []byte) Encoder { e.src = b return e } -// String implements the interface Stringer for encoder struct. +// String implements Stringer interface for Encoder struct. // 实现 Stringer 接口 -func (e encoder) String() string { +func (e Encoder) String() string { return e.ToString() } // ToString outputs as string. // 输出字符串 -func (e encoder) ToString() string { +func (e Encoder) ToString() string { return bytes2string(e.dst) } // ToBytes outputs as byte slice. // 输出字节切片 -func (e encoder) ToBytes() []byte { +func (e Encoder) ToBytes() []byte { if len(e.dst) == 0 { return []byte("") } diff --git a/encrypt.go b/encrypter.go similarity index 69% rename from encrypt.go rename to encrypter.go index d399e43..d1b9766 100644 --- a/encrypt.go +++ b/encrypter.go @@ -4,59 +4,59 @@ import ( "crypto/cipher" ) -// defines a encrypter struct. -// 定义 encrypter 结构体 -type encrypter struct { +// Encrypter defines Encrypter struct. +// 定义 Encrypter 结构体 +type Encrypter struct { dongle } -// NewEncrypter returns a new encrypter instance. -// 初始化 encrypter 结构体 -func NewEncrypter() encrypter { - return encrypter{} +// newEncrypter returns a new Encrypter instance. +// 初始化 Encrypter 结构体 +func newEncrypter() Encrypter { + return Encrypter{} } // FromString encrypts from string. // 对字符串加密 -func (e encrypter) FromString(s string) encrypter { +func (e Encrypter) FromString(s string) Encrypter { e.src = string2bytes(s) return e } // FromBytes encrypts from byte slice. // 对字节切片加密 -func (e encrypter) FromBytes(b []byte) encrypter { +func (e Encrypter) FromBytes(b []byte) Encrypter { e.src = b return e } -// String implements the interface Stringer for encrypter struct. +// String implements Stringer interface for Encrypter struct. // 实现 Stringer 接口 -func (e encrypter) String() string { +func (e Encrypter) String() string { return e.ToRawString() } // ToRawString outputs as raw string without encoding. // 输出未经编码的原始字符串 -func (e encrypter) ToRawString() string { +func (e Encrypter) ToRawString() string { return bytes2string(e.dst) } // ToHexString outputs as string with hex encoding. // 输出经过 hex 编码的字符串 -func (e encrypter) ToHexString() string { +func (e Encrypter) ToHexString() string { return Encode.FromBytes(e.dst).ByHex().ToString() } // ToBase64String outputs as string with base64 encoding. // 输出经过 base64 编码的字符串 -func (e encrypter) ToBase64String() string { +func (e Encrypter) ToBase64String() string { return Encode.FromBytes(e.dst).ByBase64().ToString() } // ToRawBytes outputs as raw byte slice without encoding. // 输出未经编码的原始字节切片 -func (e encrypter) ToRawBytes() []byte { +func (e Encrypter) ToRawBytes() []byte { if len(e.dst) == 0 { return []byte("") } @@ -65,19 +65,19 @@ func (e encrypter) ToRawBytes() []byte { // ToHexBytes outputs as byte with hex encoding. // 输出经过 hex 编码的字节切片 -func (e encrypter) ToHexBytes() []byte { +func (e Encrypter) ToHexBytes() []byte { return Encode.FromBytes(e.dst).ByHex().ToBytes() } // ToBase64Bytes outputs as byte slice with base64 encoding. // 输出经过 base64 编码的字节切片 -func (e encrypter) ToBase64Bytes() []byte { +func (e Encrypter) ToBase64Bytes() []byte { return Encode.FromBytes(e.dst).ByBase64().ToBytes() } // encrypts with given mode and padding // 根据指定的分组模式和填充模式进行加密 -func (e encrypter) encrypt(c *Cipher, b cipher.Block) (dst []byte, err error) { +func (e Encrypter) encrypt(c *Cipher, b cipher.Block) (dst []byte, err error) { src, mode, padding, size := e.src, c.mode, c.padding, b.BlockSize() if len(src) == 0 { @@ -92,6 +92,10 @@ func (e encrypter) encrypt(c *Cipher, b cipher.Block) (dst []byte, err error) { src = c.PKCS5Padding(src) case PKCS7: src = c.PKCS7Padding(src, size) + case AnsiX923: + src = c.AnsiX923Padding(src, size) + case ISO97971: + src = c.ISO97971Padding(src, size) default: return nil, invalidPaddingError(padding) } diff --git a/errors.go b/errors.go index 5b7130d..e4c75e3 100644 --- a/errors.go +++ b/errors.go @@ -22,6 +22,24 @@ var ( } ) +var ( + // returns an invalid blowfish src error + // 返回无效的 blowfish 明文错误 + invalidBlowfishSrcError = func() error { + return fmt.Errorf("blowfish: invalid src, the src is not full blocks") + } + // returns an invalid blowfish key error + // 返回无效的 blowfish 密钥错误 + invalidBlowfishKeyError = func() error { + return fmt.Errorf("blowfish: invalid key, the key must from 1 to 56 bytes") + } + // returns an invalid blowfish iv error、 + // 返回无效的 blowfish 偏移量错误 + invalidBlowfishIVError = func() error { + return fmt.Errorf("blowfish: invalid iv, the iv size must be 8 bytes") + } +) + var ( // returns an invalid des src error // 返回无效的 des 明文错误 diff --git a/hash.go b/hash.go index 8db0d96..50d81e2 100644 --- a/hash.go +++ b/hash.go @@ -14,163 +14,167 @@ import ( "golang.org/x/crypto/sha3" ) +// defines hash algorithm enum type. +// 定义哈希算法枚举类型 +type hashAlgo crypto.Hash + // hash algorithm constants -// 哈希算法常量 +// 哈希算法枚举值 const ( - MD4 = crypto.MD4 - MD5 = crypto.MD5 - SHA1 = crypto.SHA1 - SHA224 = crypto.SHA224 - SHA256 = crypto.SHA256 - SHA384 = crypto.SHA384 - SHA512 = crypto.SHA512 - RIPEMD160 = crypto.RIPEMD160 + MD4 hashAlgo = 1 + iota + MD5 + SHA1 + SHA224 + SHA256 + SHA384 + SHA512 + RIPEMD160 = 19 ) // ByMd2 encrypts by md2. // 通过 md2 加密 -func (e encrypter) ByMd2() encrypter { +func (e Encrypter) ByMd2() Encrypter { if len(e.src) == 0 { return e } - hasher := md2.New() - hasher.Write(e.src) - e.dst = hasher.Sum(nil) + h := md2.New() + h.Write(e.src) + e.dst = h.Sum(nil) return e } // ByMd4 encrypts by md4. // 通过 md4 加密 -func (e encrypter) ByMd4() encrypter { +func (e Encrypter) ByMd4() Encrypter { if len(e.src) == 0 { return e } - hasher := md4.New() - hasher.Write(e.src) - e.dst = hasher.Sum(nil) + h := md4.New() + h.Write(e.src) + e.dst = h.Sum(nil) return e } // ByMd5 encrypts by md5. // 通过 md5 加密 -func (e encrypter) ByMd5() encrypter { +func (e Encrypter) ByMd5() Encrypter { if len(e.src) == 0 { return e } - hasher := md5.New() - hasher.Write(e.src) - e.dst = hasher.Sum(nil) + h := md5.New() + h.Write(e.src) + e.dst = h.Sum(nil) return e } // BySha1 encrypts by sha1. // 通过 sha1 加密 -func (e encrypter) BySha1() encrypter { +func (e Encrypter) BySha1() Encrypter { if len(e.src) == 0 { return e } - hasher := sha1.New() - hasher.Write(e.src) - e.dst = hasher.Sum(nil) + h := sha1.New() + h.Write(e.src) + e.dst = h.Sum(nil) return e } // BySha3 encrypts by sha3. // 通过 BySha3 加密 -func (e encrypter) BySha3(size int) encrypter { - var hasher hash.Hash +func (e Encrypter) BySha3(size int) Encrypter { + var h hash.Hash if len(e.src) == 0 { return e } switch size { case 224: - hasher = sha3.New224() + h = sha3.New224() case 256: - hasher = sha3.New256() + h = sha3.New256() case 384: - hasher = sha3.New384() + h = sha3.New384() case 512: - hasher = sha3.New512() + h = sha3.New512() default: e.Error = invalidHashSizeError() return e } - hasher.Write(e.src) - e.dst = hasher.Sum(nil) + h.Write(e.src) + e.dst = h.Sum(nil) return e } // BySha224 encrypts by sha224. // 通过 sha224 加密 -func (e encrypter) BySha224() encrypter { +func (e Encrypter) BySha224() Encrypter { if len(e.src) == 0 { return e } - hasher := sha256.New224() - hasher.Write(e.src) - e.dst = hasher.Sum(nil) + h := sha256.New224() + h.Write(e.src) + e.dst = h.Sum(nil) return e } // BySha256 encrypts by sha256. // 通过 sha256 加密 -func (e encrypter) BySha256() encrypter { +func (e Encrypter) BySha256() Encrypter { if len(e.src) == 0 { return e } - hasher := sha256.New() - hasher.Write(e.src) - e.dst = hasher.Sum(nil) + h := sha256.New() + h.Write(e.src) + e.dst = h.Sum(nil) return e } // BySha384 encrypts by sha384. // 通过 sha384 加密 -func (e encrypter) BySha384() encrypter { +func (e Encrypter) BySha384() Encrypter { if len(e.src) == 0 { return e } - hasher := sha512.New384() - hasher.Write(e.src) - e.dst = hasher.Sum(nil) + h := sha512.New384() + h.Write(e.src) + e.dst = h.Sum(nil) return e } // BySha512 encrypts by sha512. // 通过 sha512 加密 -func (e encrypter) BySha512(size ...int) encrypter { - var hasher hash.Hash +func (e Encrypter) BySha512(size ...int) Encrypter { + var h hash.Hash if len(e.src) == 0 { return e } if len(size) == 0 { - hasher = sha512.New() - hasher.Write(e.src) - e.dst = hasher.Sum(nil) + h = sha512.New() + h.Write(e.src) + e.dst = h.Sum(nil) return e } switch size[0] { case 224: - hasher = sha512.New512_224() + h = sha512.New512_224() case 256: - hasher = sha512.New512_256() + h = sha512.New512_256() default: e.Error = invalidHashSizeError() return e } - hasher.Write(e.src) - e.dst = hasher.Sum(nil) + h.Write(e.src) + e.dst = h.Sum(nil) return e } // ByRipemd160 encrypts by ripemd160. // 通过 ripemd160 加密 -func (e encrypter) ByRipemd160() encrypter { +func (e Encrypter) ByRipemd160() Encrypter { if len(e.src) == 0 { return e } - hasher := ripemd160.New() - hasher.Write(e.src) - e.dst = hasher.Sum(nil) + h := ripemd160.New() + h.Write(e.src) + e.dst = h.Sum(nil) return e } diff --git a/hmac.go b/hmac.go index 06e02e3..fcbde12 100644 --- a/hmac.go +++ b/hmac.go @@ -17,161 +17,161 @@ import ( // ByHmacMd2 encrypts by hmac with md2. // 通过 hmac-md2 加密 -func (e encrypter) ByHmacMd2(key interface{}) encrypter { +func (e Encrypter) ByHmacMd2(key interface{}) Encrypter { if len(e.src) == 0 { return e } - mac := hmac.New(md2.New, interface2bytes(key)) - mac.Write(e.src) - e.dst = mac.Sum(nil) + h := hmac.New(md2.New, interface2bytes(key)) + h.Write(e.src) + e.dst = h.Sum(nil) return e } // ByHmacMd4 encrypts by hmac with md4. // 通过 hmac-md4 加密 -func (e encrypter) ByHmacMd4(key interface{}) encrypter { +func (e Encrypter) ByHmacMd4(key interface{}) Encrypter { if len(e.src) == 0 { return e } - mac := hmac.New(md4.New, interface2bytes(key)) - mac.Write(e.src) - e.dst = mac.Sum(nil) + h := hmac.New(md4.New, interface2bytes(key)) + h.Write(e.src) + e.dst = h.Sum(nil) return e } // ByHmacMd5 encrypts by hmac with md5. // 通过 hmac-md5 加密 -func (e encrypter) ByHmacMd5(key interface{}) encrypter { +func (e Encrypter) ByHmacMd5(key interface{}) Encrypter { if len(e.src) == 0 { return e } - mac := hmac.New(md5.New, interface2bytes(key)) - mac.Write(e.src) - e.dst = mac.Sum(nil) + h := hmac.New(md5.New, interface2bytes(key)) + h.Write(e.src) + e.dst = h.Sum(nil) return e } // ByHmacSha1 encrypts by hmac with sha1. // 通过 hmac-sha1 加密 -func (e encrypter) ByHmacSha1(key interface{}) encrypter { +func (e Encrypter) ByHmacSha1(key interface{}) Encrypter { if len(e.src) == 0 { return e } - mac := hmac.New(sha1.New, interface2bytes(key)) - mac.Write(e.src) - e.dst = mac.Sum(nil) + h := hmac.New(sha1.New, interface2bytes(key)) + h.Write(e.src) + e.dst = h.Sum(nil) return e } // ByHmacSha3 encrypts by hmac with sha3. // 通过 hmac-sha3 加密 -func (e encrypter) ByHmacSha3(key interface{}, size int) encrypter { +func (e Encrypter) ByHmacSha3(key interface{}, size int) Encrypter { if len(e.src) == 0 { return e } - var hashFun func() hash.Hash + var f func() hash.Hash switch size { case 224: - hashFun = sha3.New224 + f = sha3.New224 case 256: - hashFun = sha3.New256 + f = sha3.New256 case 384: - hashFun = sha3.New384 + f = sha3.New384 case 512: - hashFun = sha3.New512 + f = sha3.New512 default: e.Error = invalidHashSizeError() return e } - mac := hmac.New(hashFun, interface2bytes(key)) - mac.Write(e.src) - e.dst = mac.Sum(nil) + h := hmac.New(f, interface2bytes(key)) + h.Write(e.src) + e.dst = h.Sum(nil) return e } // ByHmacSha224 encrypts by hmac with sha224. // 通过 hmac-sha224 加密 -func (e encrypter) ByHmacSha224(key interface{}) encrypter { +func (e Encrypter) ByHmacSha224(key interface{}) Encrypter { if len(e.src) == 0 { return e } - mac := hmac.New(sha256.New224, interface2bytes(key)) - mac.Write(e.src) - e.dst = mac.Sum(nil) + h := hmac.New(sha256.New224, interface2bytes(key)) + h.Write(e.src) + e.dst = h.Sum(nil) return e } // ByHmacSha256 encrypts by hmac with sha256. // 通过 hmac-sha256 加密 -func (e encrypter) ByHmacSha256(key interface{}) encrypter { +func (e Encrypter) ByHmacSha256(key interface{}) Encrypter { if len(e.src) == 0 { return e } - mac := hmac.New(sha256.New, interface2bytes(key)) - mac.Write(e.src) - e.dst = mac.Sum(nil) + h := hmac.New(sha256.New, interface2bytes(key)) + h.Write(e.src) + e.dst = h.Sum(nil) return e } // ByHmacSha384 encrypts by hmac with sha384. // 通过 hmac-sha384 加密 -func (e encrypter) ByHmacSha384(key interface{}) encrypter { +func (e Encrypter) ByHmacSha384(key interface{}) Encrypter { if len(e.src) == 0 { return e } - mac := hmac.New(sha512.New384, interface2bytes(key)) - mac.Write(e.src) - e.dst = mac.Sum(nil) + h := hmac.New(sha512.New384, interface2bytes(key)) + h.Write(e.src) + e.dst = h.Sum(nil) return e } // ByHmacSha512 encrypts by hmac with sha512. // 通过 hmac-sha512 加密 -func (e encrypter) ByHmacSha512(key interface{}, size ...int) encrypter { +func (e Encrypter) ByHmacSha512(key interface{}, size ...int) Encrypter { if len(e.src) == 0 { return e } - var hashFun func() hash.Hash + var f func() hash.Hash if len(size) == 0 { size = []int{512} } switch size[0] { case 512: - hashFun = sha512.New + f = sha512.New case 224: - hashFun = sha512.New512_224 + f = sha512.New512_224 case 256: - hashFun = sha512.New512_256 + f = sha512.New512_256 default: e.Error = invalidHashSizeError() return e } - mac := hmac.New(hashFun, interface2bytes(key)) - mac.Write(e.src) - e.dst = mac.Sum(nil) + h := hmac.New(f, interface2bytes(key)) + h.Write(e.src) + e.dst = h.Sum(nil) return e } // ByHmacRipemd160 encrypts by hmac with ripemd160. // 通过 hmac-ripemd160 加密 -func (e encrypter) ByHmacRipemd160(key interface{}) encrypter { +func (e Encrypter) ByHmacRipemd160(key interface{}) Encrypter { if len(e.src) == 0 { return e } - mac := hmac.New(ripemd160.New, interface2bytes(key)) - mac.Write(e.src) - e.dst = mac.Sum(nil) + h := hmac.New(ripemd160.New, interface2bytes(key)) + h.Write(e.src) + e.dst = h.Sum(nil) return e } // ByHmacSm3 encrypts by hmac with sm3. // 通过 hmac-sm3 加密 -func (e encrypter) ByHmacSm3(key interface{}) encrypter { +func (e Encrypter) ByHmacSm3(key interface{}) Encrypter { if len(e.src) == 0 { return e } - mac := hmac.New(sm3.New, interface2bytes(key)) - mac.Write(e.src) - e.dst = mac.Sum(nil) + h := hmac.New(sm3.New, interface2bytes(key)) + h.Write(e.src) + e.dst = h.Sum(nil) return e } diff --git a/md2/md2.go b/md2/md2.go index b5f2bb4..6e8f435 100644 --- a/md2/md2.go +++ b/md2/md2.go @@ -107,18 +107,8 @@ func (d *digest) Sum(in []byte) []byte { dig.Write(tmp[0 : _Chunk-dig.nx]) - // At this state we should have nothing left in buffer - if dig.nx != 0 { - panic("d.nx != 0") - } - dig.Write(dig.digest[0:16]) - // At this state we should have nothing left in buffer - if dig.nx != 0 { - panic("d.nx != 0") - } - return append(in, dig.state[0:16]...) } diff --git a/morse.go b/morse.go index f7aebb5..5811368 100644 --- a/morse.go +++ b/morse.go @@ -6,7 +6,7 @@ import ( // ByMorse encodes by morse. // 通过 morse 编码 -func (e encoder) ByMorse(separator ...string) encoder { +func (e Encoder) ByMorse(separator ...string) Encoder { if len(e.src) == 0 { return e } @@ -24,7 +24,7 @@ func (e encoder) ByMorse(separator ...string) encoder { // ByMorse decodes by morse. // 通过 morse 解码 -func (d decoder) ByMorse(separator ...string) decoder { +func (d Decoder) ByMorse(separator ...string) Decoder { if len(d.src) == 0 || d.Error != nil { return d } diff --git a/rc4.go b/rc4.go index 3e9386b..c1617f3 100644 --- a/rc4.go +++ b/rc4.go @@ -6,7 +6,7 @@ import ( // ByRc4 encrypts by rc4. // 通过 rc4 加密 -func (e encrypter) ByRc4(key interface{}) encrypter { +func (e Encrypter) ByRc4(key interface{}) Encrypter { if len(e.src) == 0 { return e } @@ -23,7 +23,7 @@ func (e encrypter) ByRc4(key interface{}) encrypter { // ByRc4 decrypts by rc4. // 通过 rc4 解密 -func (d decrypter) ByRc4(key interface{}) decrypter { +func (d Decrypter) ByRc4(key interface{}) Decrypter { if len(d.src) == 0 || d.Error != nil { return d } diff --git a/rsa.go b/rsa.go index 598a04f..ac7fc32 100644 --- a/rsa.go +++ b/rsa.go @@ -10,7 +10,7 @@ import ( // ByRsa encrypts by rsa with public key. // 通过 rsa 公钥加密 -func (e encrypter) ByRsa(publicKey interface{}) encrypter { +func (e Encrypter) ByRsa(publicKey interface{}) Encrypter { if len(e.src) == 0 { return e } @@ -25,7 +25,7 @@ func (e encrypter) ByRsa(publicKey interface{}) encrypter { // ByRsa decrypts by rsa with private key. // 通过 rsa 私钥解密 -func (d decrypter) ByRsa(privateKey interface{}) decrypter { +func (d Decrypter) ByRsa(privateKey interface{}) Decrypter { if len(d.src) == 0 || d.Error != nil { return d } @@ -44,11 +44,11 @@ func (d decrypter) ByRsa(privateKey interface{}) decrypter { // ByRsa signs by rsa. // 通过 rsa 私钥签名 -func (s signer) ByRsa(privateKey interface{}, hash crypto.Hash) signer { +func (s Signer) ByRsa(privateKey interface{}, hash hashAlgo) Signer { if len(s.src) == 0 || s.Error != nil { return s } - if !isSupportedHash(hash) { + if !hash.isRsaSupported() { s.Error = invalidRsaHashError() return s } @@ -57,19 +57,19 @@ func (s signer) ByRsa(privateKey interface{}, hash crypto.Hash) signer { s.Error = err return s } - hasher := hash.New() + hasher := crypto.Hash(hash).New() hasher.Write(s.src) - s.dst, s.Error = rsa.SignPKCS1v15(rand.Reader, pri, hash, hasher.Sum(nil)) + s.dst, s.Error = rsa.SignPKCS1v15(rand.Reader, pri, crypto.Hash(hash), hasher.Sum(nil)) return s } // ByRsa verify sign by rsa with public key. // 通过 rsa 公钥验签 -func (v verifier) ByRsa(publicKey interface{}, hash crypto.Hash) verifier { +func (v Verifier) ByRsa(publicKey interface{}, hash hashAlgo) Verifier { if len(v.src) == 0 || v.Error != nil { return v } - if !isSupportedHash(hash) { + if !hash.isRsaSupported() { v.Error = invalidRsaHashError() return v } @@ -78,9 +78,9 @@ func (v verifier) ByRsa(publicKey interface{}, hash crypto.Hash) verifier { v.Error = err return v } - hasher := hash.New() + hasher := crypto.Hash(hash).New() hasher.Write(v.src) - v.Error = rsa.VerifyPKCS1v15(pub, hash, hasher.Sum(nil), v.sign) + v.Error = rsa.VerifyPKCS1v15(pub, crypto.Hash(hash), hasher.Sum(nil), v.sign) return v } @@ -122,14 +122,14 @@ func parseRsaPrivateKey(privateKey interface{}) (*rsa.PrivateKey, error) { return pri.(*rsa.PrivateKey), nil } -// whether is a supported hash function -// 判断是否是支持的哈希函数 -func isSupportedHash(hash crypto.Hash) bool { - hashes := []crypto.Hash{ +// whether is a rsa supported hash algorithm +// 判断是否是 rsa 支持的哈希算法 +func (hash hashAlgo) isRsaSupported() bool { + hashes := []hashAlgo{ MD5, SHA1, SHA224, SHA256, SHA384, SHA512, RIPEMD160, } - for _, e := range hashes { - if e == hash { + for _, val := range hashes { + if val == hash { return true } } diff --git a/safe_url.go b/safe_url.go index 41b7dc9..b8f795a 100644 --- a/safe_url.go +++ b/safe_url.go @@ -6,7 +6,7 @@ import ( // BySafeURL encodes as safe url. // 对 URL 进行转义编码 -func (e encoder) BySafeURL() encoder { +func (e Encoder) BySafeURL() Encoder { if len(e.src) == 0 { return e } @@ -16,7 +16,7 @@ func (e encoder) BySafeURL() encoder { // BySafeURL decodes as safe url. // 对 URL 进行转义解码 -func (d decoder) BySafeURL() decoder { +func (d Decoder) BySafeURL() Decoder { if len(d.src) == 0 { return d } diff --git a/sign.go b/signer.go similarity index 65% rename from sign.go rename to signer.go index 81ab95d..132b248 100644 --- a/sign.go +++ b/signer.go @@ -1,58 +1,58 @@ package dongle -// sign defines a signer struct. -// 定义 sign 结构体 -type signer struct { +// Signer defines a Signer struct. +// 定义 Signer 结构体 +type Signer struct { dongle } -// NewSigner returns a new signer instance. -// 初始化 signer 结构体 -func NewSigner() signer { - return signer{} +// newSigner returns a new Signer instance. +// 初始化 Signer 结构体 +func newSigner() Signer { + return Signer{} } // FromString signs from string. // 对字符串进行签名 -func (s signer) FromString(message string) signer { +func (s Signer) FromString(message string) Signer { s.src = string2bytes(message) return s } // FromBytes signs from byte slice. // 对字节切片进行签名 -func (s signer) FromBytes(message []byte) signer { +func (s Signer) FromBytes(message []byte) Signer { s.src = message return s } -// String implements the interface Stringer for signer struct. +// String implements Stringer interface for Signer struct. // 实现 Stringer 接口 -func (s signer) String() string { +func (s Signer) String() string { return s.ToRawString() } // ToRawString outputs as raw string without encoding. // 输出未经编码的原始字符串 -func (s signer) ToRawString() string { +func (s Signer) ToRawString() string { return bytes2string(s.dst) } // ToHexString outputs as string with hex encoding. // 输出经过 hex 编码的字符串 -func (s signer) ToHexString() string { +func (s Signer) ToHexString() string { return Encode.FromBytes(s.dst).ByHex().ToString() } // ToBase64String outputs as string with base64 encoding. // 输出经过 base64 编码的字符串 -func (s signer) ToBase64String() string { +func (s Signer) ToBase64String() string { return Encode.FromBytes(s.dst).ByBase64().ToString() } // ToRawBytes outputs as raw byte slice without encoding. // 输出未经编码的原始字节切片 -func (s signer) ToRawBytes() []byte { +func (s Signer) ToRawBytes() []byte { if len(s.dst) == 0 { return []byte("") } @@ -61,12 +61,12 @@ func (s signer) ToRawBytes() []byte { // ToHexBytes outputs as byte with hex encoding. // 输出经过 hex 编码的字节切片 -func (s signer) ToHexBytes() []byte { +func (s Signer) ToHexBytes() []byte { return Encode.FromBytes(s.dst).ByHex().ToBytes() } // ToBase64Bytes outputs as byte slice with base64 encoding. // 输出经过 base64 编码的字节切片 -func (s signer) ToBase64Bytes() []byte { +func (s Signer) ToBase64Bytes() []byte { return Encode.FromBytes(s.dst).ByBase64().ToBytes() } diff --git a/sm3.go b/sm3.go index 5a5534d..dc5d3f7 100644 --- a/sm3.go +++ b/sm3.go @@ -6,12 +6,12 @@ import ( // BySm3 encrypts by sm3. // 通过 sm3 加密 -func (e encrypter) BySm3() encrypter { +func (e Encrypter) BySm3() Encrypter { if len(e.src) == 0 { return e } - hasher := sm3.New() - hasher.Write(e.src) - e.dst = hasher.Sum(nil) + h := sm3.New() + h.Write(e.src) + e.dst = h.Sum(nil) return e } diff --git a/tea.go b/tea.go index de4c50c..c877b2e 100644 --- a/tea.go +++ b/tea.go @@ -6,7 +6,7 @@ import ( // ByTea encrypts by tea. // 通过 tea 加密 -func (e encrypter) ByTea(key interface{}, rounds ...int) encrypter { +func (e Encrypter) ByTea(key interface{}, rounds ...int) Encrypter { if len(e.src) == 0 { return e } @@ -35,7 +35,7 @@ func (e encrypter) ByTea(key interface{}, rounds ...int) encrypter { // ByTea decrypts by tea. // 通过 tea 解密 -func (d decrypter) ByTea(key interface{}, rounds ...int) decrypter { +func (d Decrypter) ByTea(key interface{}, rounds ...int) Decrypter { if len(d.src) == 0 || d.Error != nil { return d } diff --git a/verify.go b/verifier.go similarity index 57% rename from verify.go rename to verifier.go index a673d2c..9481dac 100644 --- a/verify.go +++ b/verifier.go @@ -1,21 +1,21 @@ package dongle -// defines a verifier struct. -// 定义 verifier 结构体 -type verifier struct { +// Verifier defines a Verifier struct. +// 定义 Verifier 结构体 +type Verifier struct { dongle sign []byte } -// NewVerifier returns a new verifier instance. -// 初始化 verify 结构体 -func NewVerifier() verifier { - return verifier{} +// newVerifier returns a new Verifier instance. +// 初始化 Verifier 结构体 +func newVerifier() Verifier { + return Verifier{} } // FromRawString verify signature from raw string. // 对未经编码的原始字符串签名进行验签 -func (v verifier) FromRawString(signature, message string) verifier { +func (v Verifier) FromRawString(signature, message string) Verifier { v.src = string2bytes(message) v.sign = string2bytes(signature) return v @@ -23,33 +23,33 @@ func (v verifier) FromRawString(signature, message string) verifier { // FromHexString decrypts from string with hex encoding. // 对经过 hex 编码的字符串签名进行验签 -func (v verifier) FromHexString(signature, message string) verifier { - decode := Decode.FromString(signature).ByHex() - if decode.Error != nil { +func (v Verifier) FromHexString(signature, message string) Verifier { + d := Decode.FromString(signature).ByHex() + if d.Error != nil { v.Error = invalidDecodingError("hex") return v } - v.sign = decode.ToBytes() + v.sign = d.ToBytes() v.src = string2bytes(message) return v } // FromBase64String decrypts from string with base64 encoding. // 对经过 base64 编码的字符串签名进行验签 -func (v verifier) FromBase64String(signature, message string) verifier { - decode := Decode.FromString(signature).ByBase64() - if decode.Error != nil { +func (v Verifier) FromBase64String(signature, message string) Verifier { + d := Decode.FromString(signature).ByBase64() + if d.Error != nil { v.Error = invalidDecodingError("base64") return v } - v.sign = decode.ToBytes() + v.sign = d.ToBytes() v.src = string2bytes(message) return v } // FromRawBytes verify signature from raw byte slice. // 对未经编码的原始字节切片签名进行验签 -func (v verifier) FromRawBytes(signature, message []byte) verifier { +func (v Verifier) FromRawBytes(signature, message []byte) Verifier { v.sign = signature v.src = message return v @@ -57,33 +57,33 @@ func (v verifier) FromRawBytes(signature, message []byte) verifier { // FromHexBytes verify from byte slice with hex encoding. // 对经过 hex 编码的字节切片签名进行验签 -func (v verifier) FromHexBytes(signature, message []byte) verifier { - decode := Decode.FromBytes(signature).ByHex() - if decode.Error != nil { +func (v Verifier) FromHexBytes(signature, message []byte) Verifier { + d := Decode.FromBytes(signature).ByHex() + if d.Error != nil { v.Error = invalidDecodingError("hex") return v } - v.sign = decode.ToBytes() + v.sign = d.ToBytes() v.src = message return v } // FromBase64Bytes verify from byte slice with base64 encoding. // 对经过 base64 编码的字节切片签名进行验签 -func (v verifier) FromBase64Bytes(signature, message []byte) verifier { - decode := Decode.FromBytes(signature).ByBase64() - if decode.Error != nil { +func (v Verifier) FromBase64Bytes(signature, message []byte) Verifier { + d := Decode.FromBytes(signature).ByBase64() + if d.Error != nil { v.Error = invalidDecodingError("base64") return v } - v.sign = decode.ToBytes() + v.sign = d.ToBytes() v.src = message return v } // ToBool outputs as bool. // 输出布尔值 -func (v verifier) ToBool() bool { +func (v Verifier) ToBool() bool { if len(v.src) == 0 || len(v.sign) == 0 { return false }