Update crypto.go and crypto_test.go
Replace MD4 with MD5 in HashTypes map and update test cases for MD4 and HMac functions. Added new functions for AES256 encryption and decryption.
This commit is contained in:
parent
adc7d5f59d
commit
5df108772b
5 changed files with 244 additions and 9 deletions
105
crypto/aes.go
Normal file
105
crypto/aes.go
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// AES256Encrypt AES Encrypt
|
||||
func AES256Encrypt(key string, algorithm string, nonce string, text string, additionalData string, encoding ...string) (string, error) {
|
||||
switch algorithm {
|
||||
case "GCM":
|
||||
var add []byte
|
||||
if additionalData != "" {
|
||||
add = []byte(additionalData)
|
||||
}
|
||||
ciphertext, err := aes256GCMEncrypt([]byte(key), []byte(nonce), []byte(text), add)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(encoding) > 0 && encoding[0] == "base64" {
|
||||
return base64.StdEncoding.EncodeToString(ciphertext), nil
|
||||
}
|
||||
return hex.EncodeToString(ciphertext), nil
|
||||
}
|
||||
return "", fmt.Errorf("algorithm %s not support", algorithm)
|
||||
}
|
||||
|
||||
// AES256Decrypt AES Decrypt
|
||||
func AES256Decrypt(key string, algorithm string, nonce string, ciphertext string, additionalData string, encoding ...string) (string, error) {
|
||||
switch algorithm {
|
||||
case "GCM":
|
||||
var bytes []byte
|
||||
var err error
|
||||
if len(encoding) > 0 && encoding[0] == "base64" {
|
||||
bytes, err = base64.StdEncoding.DecodeString(ciphertext)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
} else {
|
||||
bytes, err = hex.DecodeString(ciphertext)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
var add []byte
|
||||
if additionalData != "" {
|
||||
add = []byte(additionalData)
|
||||
}
|
||||
text, err := aes256GCMDecrypt([]byte(key), []byte(nonce), bytes, add)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(text), nil
|
||||
}
|
||||
return "", fmt.Errorf("algorithm %s not support", algorithm)
|
||||
}
|
||||
|
||||
func aes256GCMDecrypt(key, nonce, ciphertext, additionalData []byte) ([]byte, error) {
|
||||
if len(key) != 32 {
|
||||
return nil, fmt.Errorf("key length must be 32")
|
||||
}
|
||||
|
||||
c, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gcm, err := cipher.NewGCM(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
decrypted, err := gcm.Open(nil, nonce, ciphertext, []byte(additionalData))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("gcm open error: %s", err)
|
||||
}
|
||||
|
||||
return decrypted, nil
|
||||
}
|
||||
|
||||
func aes256GCMEncrypt(key, nonce, text, additionalData []byte) ([]byte, error) {
|
||||
|
||||
if len(key) != 32 {
|
||||
return nil, fmt.Errorf("key length must be 32")
|
||||
}
|
||||
|
||||
c, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create a GCM block mode instance
|
||||
gcm, err := cipher.NewGCM(c)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("gcm error: %s", err)
|
||||
}
|
||||
|
||||
ciphertext := gcm.Seal(nil, nonce, text, additionalData)
|
||||
return ciphertext, nil
|
||||
}
|
||||
88
crypto/aes_test.go
Normal file
88
crypto/aes_test.go
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/gou/process"
|
||||
)
|
||||
|
||||
func TestAES256GCM(t *testing.T) {
|
||||
key := `oxxxyXVBqwqUjmbgKlwuHV2mgxxxcfOa`
|
||||
nonce := `LJEcFT6QWjkG`
|
||||
text := `{"name":"yao"}`
|
||||
additionalData := `transaction`
|
||||
|
||||
crypted, err := AES256Encrypt(key, "GCM", nonce, text, additionalData)
|
||||
if err != nil {
|
||||
t.Errorf("AES256Encrypt error: %s", err)
|
||||
}
|
||||
|
||||
decrypted, err := AES256Decrypt(key, "GCM", nonce, crypted, additionalData)
|
||||
if err != nil {
|
||||
t.Errorf("AES256Decrypt error: %s", err)
|
||||
}
|
||||
|
||||
assert.Equal(t, text, decrypted)
|
||||
}
|
||||
|
||||
func TestAES256GCMBase64(t *testing.T) {
|
||||
key := `oxxxyXVBqwqUjmbgKlwuHV2mgxxxcfOa`
|
||||
nonce := `LJEcFT6QWjkG`
|
||||
text := `{"name":"yao"}`
|
||||
additionalData := `transaction`
|
||||
|
||||
crypted, err := AES256Encrypt(key, "GCM", nonce, text, additionalData, "base64")
|
||||
if err != nil {
|
||||
t.Errorf("AES256Encrypt error: %s", err)
|
||||
}
|
||||
|
||||
decrypted, err := AES256Decrypt(key, "GCM", nonce, crypted, additionalData, "base64")
|
||||
if err != nil {
|
||||
t.Errorf("AES256Decrypt error: %s", err)
|
||||
}
|
||||
assert.Equal(t, text, decrypted)
|
||||
|
||||
}
|
||||
|
||||
func TestAES256ProcessGCM(t *testing.T) {
|
||||
key := `oxxxyXVBqwqUjmbgKlwuHV2mgxxxcfOa`
|
||||
nonce := `LJEcFT6QWjkG`
|
||||
text := `{"name":"yao"}`
|
||||
additionalData := `transaction`
|
||||
|
||||
args := []interface{}{"GCM", key, nonce, text, additionalData}
|
||||
crypted, err := process.New("crypto.Aes256Encrypt", args...).Exec()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
args = []interface{}{"GCM", key, nonce, crypted, additionalData}
|
||||
decrypted, err := process.New("crypto.Aes256Decrypt", args...).Exec()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, text, decrypted)
|
||||
}
|
||||
|
||||
func TestAES256ProcessGCMBase64(t *testing.T) {
|
||||
key := `oxxxyXVBqwqUjmbgKlwuHV2mgxxxcfOa`
|
||||
nonce := `LJEcFT6QWjkG`
|
||||
text := `{"name":"yao"}`
|
||||
additionalData := `transaction`
|
||||
|
||||
args := []interface{}{"GCM", key, nonce, text, additionalData, "base64"}
|
||||
crypted, err := process.New("crypto.Aes256Encrypt", args...).Exec()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
args = []interface{}{"GCM", key, nonce, crypted, additionalData, "base64"}
|
||||
decrypted, err := process.New("crypto.Aes256Decrypt", args...).Exec()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, text, decrypted)
|
||||
}
|
||||
|
|
@ -12,17 +12,11 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/crypto/md4"
|
||||
)
|
||||
|
||||
func init() {
|
||||
crypto.RegisterHash(crypto.MD4, md4.New)
|
||||
}
|
||||
|
||||
// HashTypes string
|
||||
var HashTypes = map[string]crypto.Hash{
|
||||
"MD4": crypto.MD4,
|
||||
"MD4": crypto.MD5, // MD4 is not supported | replaced with MD5
|
||||
"MD5": crypto.MD5,
|
||||
"SHA1": crypto.SHA1,
|
||||
"SHA224": crypto.SHA224,
|
||||
|
|
|
|||
|
|
@ -11,12 +11,12 @@ func TestMD4(t *testing.T) {
|
|||
// Hash
|
||||
args := []interface{}{"MD4", "123456"}
|
||||
res := process.New("crypto.Hash", args...).Run()
|
||||
assert.Equal(t, "585028aa0f794af812ee3be8804eb14a", res)
|
||||
assert.Equal(t, "e10adc3949ba59abbe56e057f20f883e", res)
|
||||
|
||||
// HMac
|
||||
args = append(args, "123456")
|
||||
res = process.New("crypto.Hmac", args...).Run()
|
||||
assert.Equal(t, "356f45727db95d65843b2794474d741c", res)
|
||||
assert.Equal(t, "30ce71a73bdd908c3955a90e8f7429ef", res)
|
||||
}
|
||||
|
||||
func TestMD5(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ func init() {
|
|||
|
||||
process.Register("crypto.rsa2sign", ProcessRsa2Sign)
|
||||
process.Register("crypto.rsa2verify", ProcessRsa2Verify)
|
||||
process.Register("crypto.aes256encrypt", ProcessAes256Encrypt)
|
||||
process.Register("crypto.aes256decrypt", ProcessAes256Decrypt)
|
||||
}
|
||||
|
||||
// ProcessRSA2 yao.crypto.rsa Crypto RSA
|
||||
|
|
@ -100,6 +102,7 @@ func ProcessRsa2Sign(process *process.Process) interface{} {
|
|||
// Args[1] string: the hash function name. MD4/MD5/SHA1/SHA224/SHA256/SHA384/SHA512/MD5SHA1/RIPEMD160/SHA3_224/SHA3_256/SHA3_384/SHA3_512/SHA512_224/SHA512_256/BLAKE2s_256/BLAKE2b_256/BLAKE2b_384/BLAKE2b_512
|
||||
// Args[2] string: value
|
||||
// Args[3] string: sign
|
||||
// Args[4] string: "base64" (optional)
|
||||
func ProcessRsa2Verify(process *process.Process) interface{} {
|
||||
process.ValidateArgNums(4)
|
||||
pub := process.ArgsString(0)
|
||||
|
|
@ -119,3 +122,48 @@ func ProcessRsa2Verify(process *process.Process) interface{} {
|
|||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// ProcessAes256Encrypt crypto.aes256encrypt
|
||||
// Args[0] string: the algorithm "GCM"
|
||||
// Args[1] string: the key
|
||||
// Args[2] string: the nonce
|
||||
// Args[3] string: the text
|
||||
// Args[4] string: the additionalData
|
||||
// Args[5] string: "base64" (optional)
|
||||
func ProcessAes256Encrypt(process *process.Process) interface{} {
|
||||
process.ValidateArgNums(4)
|
||||
algorithm := process.ArgsString(0)
|
||||
key := process.ArgsString(1)
|
||||
nonce := process.ArgsString(2)
|
||||
text := process.ArgsString(3)
|
||||
additionalData := process.ArgsString(4)
|
||||
encoding := process.ArgsString(5)
|
||||
|
||||
res, err := AES256Encrypt(key, algorithm, nonce, text, additionalData, encoding)
|
||||
if err != nil {
|
||||
exception.Err(err, 500).Throw()
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// ProcessAes256Decrypt crypto.aes256decrypt
|
||||
// Args[0] string: the algorithm "GCM"
|
||||
// Args[1] string: the key
|
||||
// Args[2] string: the nonce
|
||||
// Args[3] string: the crypted
|
||||
// Args[4] string: the additionalData
|
||||
// Args[5] string: "base64" (optional)
|
||||
func ProcessAes256Decrypt(process *process.Process) interface{} {
|
||||
process.ValidateArgNums(4)
|
||||
algorithm := process.ArgsString(0)
|
||||
key := process.ArgsString(1)
|
||||
nonce := process.ArgsString(2)
|
||||
crypted := process.ArgsString(3)
|
||||
additionalData := process.ArgsString(4)
|
||||
encoding := process.ArgsString(5)
|
||||
res, err := AES256Decrypt(key, algorithm, nonce, crypted, additionalData, encoding)
|
||||
if err != nil {
|
||||
exception.Err(err, 500).Throw()
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue