1
0
mirror of https://github.com/charlienet/go-mixed.git synced 2025-07-17 16:12:42 +08:00

加密包装

This commit is contained in:
2022-03-27 10:21:30 +08:00
parent 22f41aeeeb
commit 12865abe26
14 changed files with 1068 additions and 0 deletions

87
crypto/aes.go Normal file
View File

@ -0,0 +1,87 @@
package crypto
import (
"crypto/aes"
"crypto/cipher"
)
type aesBlock struct {
blockCipher
key []byte
}
func Aes(key []byte) *aesBlock {
return &aesBlock{key: key}
}
type aesEcbBlock struct {
*aesBlock
}
func (o *aesBlock) newCipher() (cipher.Block, error) {
return aes.NewCipher(o.key)
}
func (o *aesBlock) ECB() *aesEcbBlock {
return &aesEcbBlock{o}
}
var (
defaultAesIV = make([]byte, aes.BlockSize)
)
type aesCbcBlock struct {
*aesBlock
iv []byte
}
func (o *aesBlock) CBC() *aesCbcBlock {
return &aesCbcBlock{
aesBlock: o,
iv: defaultAesIV,
}
}
func (o *aesCbcBlock) WithIV(iv []byte) *aesCbcBlock {
o.iv = iv
return o
}
func (o *aesEcbBlock) Encrypt(msg []byte) ([]byte, error) {
block, err := o.newCipher()
if err != nil {
return nil, err
}
return o.ecbEncrypt(block, msg)
}
func (o *aesEcbBlock) Decrypt(cipherText []byte) ([]byte, error) {
block, err := o.newCipher()
if err != nil {
return nil, err
}
return o.ecbDecrypt(block, cipherText)
}
func (o *aesCbcBlock) Encrypt(msg []byte) ([]byte, error) {
block, err := o.newCipher()
if err != nil {
return nil, err
}
c := cipher.NewCBCEncrypter(block, o.iv)
return o.encrypt(c, msg)
}
func (o *aesCbcBlock) Decrypt(chiperText []byte) ([]byte, error) {
block, err := o.newCipher()
if err != nil {
return nil, err
}
c := cipher.NewCBCEncrypter(block, o.iv)
return o.decrypt(c, chiperText)
}

58
crypto/block.go Normal file
View File

@ -0,0 +1,58 @@
package crypto
import (
"crypto/cipher"
"errors"
)
type blockCipher struct {
}
func (b *blockCipher) ecbEncrypt(block cipher.Block, data []byte) ([]byte, error) {
bs := block.BlockSize()
data = PKCS7Padding(data, bs)
out := make([]byte, len(data))
dst := out
for len(data) > 0 {
block.Encrypt(dst, data[:bs])
data = data[bs:]
dst = dst[bs:]
}
return out, nil
}
func (b *blockCipher) ecbDecrypt(block cipher.Block, cipherText []byte) ([]byte, error) {
bs := block.BlockSize()
if len(cipherText)%bs != 0 {
return nil, errors.New("DecryptDES crypto/cipher: input not full blocks")
}
out := make([]byte, len(cipherText))
dst := out
for len(cipherText) > 0 {
block.Decrypt(dst, cipherText[:bs])
cipherText = cipherText[bs:]
dst = dst[bs:]
}
return PKCS7UnPadding(out), nil
}
func (b *blockCipher) encrypt(block cipher.BlockMode, data []byte) ([]byte, error) {
data = PKCS7Padding(data, block.BlockSize())
out := make([]byte, len(data))
block.CryptBlocks(out, data)
return out, nil
}
func (b *blockCipher) decrypt(block cipher.BlockMode, cipherText []byte) ([]byte, error) {
out := make([]byte, len(cipherText))
block.CryptBlocks(out, cipherText)
return PKCS7UnPadding(out), nil
}

95
crypto/des.go Normal file
View File

@ -0,0 +1,95 @@
package crypto
import (
"crypto/cipher"
"crypto/des"
"errors"
"strconv"
)
type desInstance struct {
blockCipher
key []byte
}
func Des(key []byte) *desInstance {
return &desInstance{key: key}
}
// 包含des和3des根据不同的密钥长度计算
func (o *desInstance) newCipher() (cipher.Block, error) {
switch len(o.key) {
case 8:
return des.NewCipher(o.key)
case 24:
return des.NewTripleDESCipher(o.key)
default:
return nil, errors.New("crypto/des: invalid key size " + strconv.Itoa(len(o.key)))
}
}
type desEcb struct {
*desInstance
}
func (o *desInstance) ECB() *desEcb {
return &desEcb{desInstance: o}
}
func (o *desEcb) Encrypt(data []byte) ([]byte, error) {
block, err := o.newCipher()
if err != nil {
return nil, err
}
return o.ecbEncrypt(block, data)
}
func (o *desEcb) Decrypt(cipherText []byte) ([]byte, error) {
block, err := o.newCipher()
if err != nil {
return nil, err
}
return o.ecbDecrypt(block, cipherText)
}
var (
defaultIV = make([]byte, des.BlockSize)
)
type desCbc struct {
*desInstance
iv []byte
}
func (o *desInstance) Cbc() *desCbc {
return &desCbc{desInstance: o, iv: defaultIV}
}
func (o *desCbc) WithIV(iv []byte) *desCbc {
o.iv = iv
return o
}
func (o *desCbc) Encrypt(data []byte) ([]byte, error) {
block, err := o.newCipher()
if err != nil {
return nil, err
}
e := cipher.NewCBCEncrypter(block, o.iv)
return o.encrypt(e, data)
}
func (o *desCbc) Decrypt(cipherText []byte) ([]byte, error) {
block, err := o.newCipher()
if err != nil {
return nil, err
}
d := cipher.NewCBCDecrypter(block, o.iv)
return o.decrypt(d, cipherText)
}

38
crypto/des_test.go Normal file
View File

@ -0,0 +1,38 @@
package crypto_test
import (
"crypto/aes"
"crypto/des"
"encoding/hex"
"testing"
"github.com/charlienet/go-mixed/crypto"
)
func TestDes(t *testing.T) {
key, _ := hex.DecodeString("0123456789ABCDEF")
msg, _ := hex.DecodeString("F0A2B07E64DD2C25")
c, err := crypto.Des(key).ECB().Encrypt(msg)
t.Log(hex.EncodeToString(c), err)
c, err = crypto.Des(key).Cbc().Encrypt(msg)
t.Log(hex.EncodeToString(c), err)
d, err := crypto.Des(key).Cbc().Decrypt(c)
t.Log(hex.EncodeToString(d), err)
}
func TestTripleDES(t *testing.T) {
key, _ := hex.DecodeString("0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF")
block, err := des.NewTripleDESCipher(key)
t.Log(block, err, block.BlockSize())
}
func TestAes(t *testing.T) {
t.Log(aes.BlockSize)
key, _ := hex.DecodeString("0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF")
msg, _ := hex.DecodeString("F0A2B07E64DD2C25")
c, err := crypto.Aes(key).ECB().Encrypt(msg)
t.Log(hex.EncodeToString(c), err)
}

100
crypto/ecdsa.go Normal file
View File

@ -0,0 +1,100 @@
package crypto
import (
"crypto"
"crypto/ecdsa"
"crypto/x509"
"encoding/pem"
"errors"
"math/big"
"strconv"
)
type ecdsaOptions struct {
hashOptions
prv *ecdsa.PrivateKey
pub *ecdsa.PublicKey
}
type Option interface {
apply(*ecdsaOptions) error
}
type hash2Option interface {
apply(*hashOptions) error
}
type privateKeyOption []byte
func (p privateKeyOption) apply(opts *ecdsaOptions) error {
block, _ := pem.Decode(p)
prv, err := x509.ParseECPrivateKey(block.Bytes)
if err != nil {
return err
}
opts.prv = prv
return nil
}
type publicKeyOption []byte
func (p publicKeyOption) apply(opts *ecdsaOptions) error {
block, _ := pem.Decode(p)
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return err
}
opts.pub = pub.(*ecdsa.PublicKey)
return nil
}
type hashOption crypto.Hash
func (p hashOption) apply(opts *hashOptions) error {
opts.h = crypto.Hash(p)
return nil
}
func NewEcdsa(h Hash, opts ...Option) (*ecdsaOptions, error) {
i := &ecdsaOptions{}
sh := crypto.Hash(h)
if !sh.Available() {
return nil, errors.New("unknown hash value " + strconv.Itoa(int(h)))
}
i.h = sh
for _, v := range opts {
if err := v.apply(i); err != nil {
return nil, err
}
}
return i, nil
}
func WithHash2(h Hash) hash2Option {
return hashOption(h)
}
func ParsePrivateKey(pem []byte) Option {
return privateKeyOption(pem)
}
func ParsePublicKey(pem []byte) Option {
return publicKeyOption(pem)
}
func (opt *ecdsaOptions) Verify(msg, rText, sText []byte) bool {
var r, s big.Int
_ = r.UnmarshalText(rText)
_ = s.UnmarshalText(sText)
sum := opt.getHash(msg)
return ecdsa.Verify(opt.pub, sum, &r, &s)
}

35
crypto/ecdsa_test.go Normal file
View File

@ -0,0 +1,35 @@
package crypto_test
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/x509"
"encoding/asn1"
"encoding/pem"
"fmt"
"testing"
"github.com/charlienet/go-mixed/crypto"
)
func TestEsda(t *testing.T) {
prv, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
t.Log(err)
ecd, err := x509.MarshalECPrivateKey(prv)
t.Log(err)
secp256r1, _ := asn1.Marshal(asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7})
fmt.Println(string(pem.EncodeToMemory(&pem.Block{Type: "EC PARAMETERS", Bytes: secp256r1})))
b := pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: ecd})
fmt.Println(string(b))
}
func TestSign(t *testing.T) {
ecdsa, err := crypto.NewEcdsa(crypto.SHA1)
t.Log(err)
_ = ecdsa
}

15
crypto/padding.go Normal file
View File

@ -0,0 +1,15 @@
package crypto
import "bytes"
func PKCS7Padding(src []byte, blockSize int) []byte {
padding := blockSize - len(src)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(src, padtext...)
}
func PKCS7UnPadding(src []byte) []byte {
length := len(src)
unpadding := int(src[length-1])
return src[:(length - unpadding)]
}

116
crypto/rsa.go Normal file
View File

@ -0,0 +1,116 @@
package crypto
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"errors"
"strconv"
)
type rsaInstance struct {
hashOptions
prk *rsa.PrivateKey
puk *rsa.PublicKey
}
type rsaOption func(o *rsaInstance) error
func NewRsa(h Hash, opts ...rsaOption) (*rsaInstance, error) {
o := &rsaInstance{}
sh := crypto.Hash(h)
if !sh.Available() {
return nil, errors.New("unknown hash value " + strconv.Itoa(int(h)))
}
o.h = sh
for _, f := range opts {
if err := f(o); err != nil {
return nil, err
}
}
// 未设置私钥时随机生成密钥
if o.prk == nil {
prk, err := rsa.GenerateKey(rand.Reader, defaultRsaBits)
if err != nil {
return nil, err
}
o.prk = prk
}
// 公钥未设置时从私钥导出
if o.puk == nil {
o.puk = &o.prk.PublicKey
}
return o, nil
}
func ParsePKCS1PrivateKey(p []byte) rsaOption {
return func(o *rsaInstance) error {
block, _ := pem.Decode(p)
if block == nil {
return errors.New("failed to decode private key")
}
prk, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return err
}
o.prk = prk
return nil
}
}
func ParsePKIXPublicKey(p []byte) rsaOption {
return func(o *rsaInstance) error {
block, _ := pem.Decode(p)
if block == nil {
return errors.New("failed to decode public key")
}
k, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return err
}
puk := k.(*rsa.PublicKey)
o.puk = puk
return nil
}
}
func (o *rsaInstance) Encrypt(msg []byte) ([]byte, error) {
return rsa.EncryptPKCS1v15(rand.Reader, o.puk, msg)
}
func (o *rsaInstance) Decrypt(ciphertext []byte) ([]byte, error) {
return rsa.DecryptPKCS1v15(rand.Reader, o.prk, ciphertext)
}
func (o *rsaInstance) Sign(msg []byte) ([]byte, error) {
hashed := o.getHash(msg)
sign, err := rsa.SignPKCS1v15(rand.Reader, o.prk, o.h, hashed)
return sign, err
}
func (o *rsaInstance) Verify(msg, sign []byte) bool {
hashed := o.getHash(msg)
if err := rsa.VerifyPKCS1v15(o.puk, o.h, hashed, sign); err != nil {
return false
}
return true
}

129
crypto/rsa_test.go Normal file
View File

@ -0,0 +1,129 @@
package crypto_test
import (
"context"
"encoding/base64"
"encoding/hex"
"testing"
"github.com/charlienet/go-mixed/crypto"
)
func TestRsaSign(t *testing.T) {
rsa, err := crypto.NewRsa(crypto.SHA256)
t.Log(rsa, err)
msg := []byte("123456")
sign, err := rsa.Sign(msg)
t.Log(base64.StdEncoding.EncodeToString(sign))
t.Log(hex.EncodeToString(sign), err)
t.Log(rsa.Verify(msg, sign))
}
func TestEncrypt(t *testing.T) {
rsa, err := crypto.NewRsa(crypto.SHA1)
t.Log(rsa, err)
msg := []byte("123456")
cipherText, err := rsa.Encrypt(msg)
t.Log(base64.StdEncoding.EncodeToString(cipherText), err)
decrypted, err := rsa.Decrypt(cipherText)
t.Log(string(decrypted), err)
}
const (
pkBytes = `-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----`
badPubBytes = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDWKn2UPL1SmlufOkgMJHDqLhjf
vyT55z2MZRzeLqB3u8YlRLUD8zi3kmQy6loHQFu0FR7en/DI9EWRXARxMKhbH+CM
yzwmdh9QlzpMrQk0p4e5VtM5pXX9d4B4XxKBXBrmp2n/1D3+oovzD6p37dqqsgPH
xOQ3KQNxnTteS00kzQIDAQAB
-----END PUBLIC KEY-----`
)
func TestParseKey(t *testing.T) {
rsa, err := crypto.NewRsa(
crypto.SHA1,
crypto.ParsePKCS1PrivateKey([]byte(pkBytes)))
t.Log(rsa, err)
msg := []byte("123456")
sign, err := rsa.Sign(msg)
t.Log(base64.StdEncoding.EncodeToString(sign))
t.Log(hex.EncodeToString(sign), err)
t.Log(rsa.Verify(msg, sign))
}
func TestBadPubKey(t *testing.T) {
context.TODO()
rsa, err := crypto.NewRsa(
crypto.SHA1,
crypto.ParsePKCS1PrivateKey([]byte(pkBytes)),
crypto.ParsePKIXPublicKey([]byte(badPubBytes)))
t.Log(rsa, err)
msg := []byte("123456")
sign, err := rsa.Sign(msg)
t.Log(base64.StdEncoding.EncodeToString(sign))
t.Log(hex.EncodeToString(sign), err)
t.Log(rsa.Verify(msg, sign))
}

109
crypto/sm2.go Normal file
View File

@ -0,0 +1,109 @@
package crypto
import (
"crypto/rand"
"errors"
"fmt"
s "github.com/tjfoc/gmsm/sm2"
x "github.com/tjfoc/gmsm/x509"
)
var (
defaultMode = C1C3C2
C1C3C2 = 0
C1C2C3 = 1
)
type sm2Instance struct {
mode int
prk *s.PrivateKey
puk *s.PublicKey
}
type option func(*sm2Instance) error
func NewSm2(opts ...option) (*sm2Instance, error) {
o := &sm2Instance{
mode: defaultMode,
}
for _, f := range opts {
if err := f(o); err != nil {
return o, err
}
}
if o.prk == nil {
priv, err := s.GenerateKey(rand.Reader)
if err != nil {
return nil, err
}
o.prk = priv
}
if o.puk == nil {
o.puk = &o.prk.PublicKey
}
return o, nil
}
func ParseSm2PrivateKey(p []byte, pwd []byte) option {
return func(so *sm2Instance) error {
fmt.Println(string(p))
priv, err := x.ReadPrivateKeyFromPem(p, pwd)
if err != nil {
return err
}
so.prk = priv
return nil
}
}
func ParseSm2PublicKey(p []byte) option {
return func(so *sm2Instance) error {
pub, err := x.ReadPublicKeyFromPem(p)
if err != nil {
return err
}
so.puk = pub
return nil
}
}
func WithMode(mode int) option {
return func(so *sm2Instance) error {
so.mode = mode
return nil
}
}
func (o *sm2Instance) Encrypt(msg []byte) ([]byte, error) {
return s.Encrypt(o.puk, msg, rand.Reader, o.mode)
}
func (o *sm2Instance) Decrypt(cipherText []byte) ([]byte, error) {
return s.Decrypt(o.prk, cipherText, o.mode)
}
func (o *sm2Instance) Sign(msg []byte) ([]byte, error) {
if o.prk == nil {
return []byte{}, errors.New("private key is nil")
}
b, e := o.prk.Sign(rand.Reader, msg, nil)
return b, e
}
func (o *sm2Instance) Verify(msg []byte, sign []byte) bool {
if o.puk == nil {
return false
}
return o.puk.Verify(msg, sign)
}

99
crypto/sm2_test.go Normal file
View File

@ -0,0 +1,99 @@
package crypto_test
import (
"crypto/x509"
"encoding/hex"
"encoding/pem"
"fmt"
"testing"
"github.com/charlienet/go-mixed/crypto"
)
func TestNewSm2(t *testing.T) {
o, err := crypto.NewSm2()
t.Logf("%+v, %v", o, err)
t.Log(crypto.NewSm2(crypto.ParseSm2PrivateKey([]byte{}, []byte{})))
msg := []byte("123456")
sign, err := o.Sign(msg)
t.Log(hex.EncodeToString(sign), err)
ok := o.Verify(msg, sign)
if !ok {
t.Fail()
}
t.Log(ok)
}
const (
privPem = `-----BEGIN ENCRYPTED PRIVATE KEY-----
MIH8MFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAgXsd3MYu0BwwICCAAw
DAYIKoZIhvcNAgcFADAdBglghkgBZQMEASoEEJzb8/1Aqhbv2cf777VoW0cEgaAz
DbRJgs76YYpya9wiaZeAavSn8Ydi+CYSvvQurqa1q0Hmna/Lgcgt2Z0F3fFN/EYP
wmDCd6SQ5hdPfQLBtkpDQdFylIHAm26O0smciB7NlfWSdgIluFacbMJ++/YHvcDp
yl1qcRpjk+s+1+8YBUp7Mp1CXbDXdQebH9xezOE3OH8+9zO3qi5qeLEVofgRQJIY
k8EBbLsGMy4WlSr0u29A
-----END ENCRYPTED PRIVATE KEY-----`
pubPem = `-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEvfHGxZL/wzWLYgPsHEpFxCCwXKSr
XExvTJS6FAem+lQTyHwOGT+qFf67J77d5y/exn6E5br79nsJkoM/7A72nQ==
-----END PUBLIC KEY-----`
badPubPem = `-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE3Og1rzeSs2wO9+YFIdgnAES03u1n
hslcifiQY8173nHtaB3R6T0PwRQTwKbpdec0dwVCpvVcdzHtivndlG0mqQ==
-----END PUBLIC KEY-----`
)
func TestPrivatePem(t *testing.T) {
signer, err := crypto.NewSm2(
crypto.ParseSm2PrivateKey([]byte(privPem), []byte{}),
crypto.ParseSm2PublicKey([]byte(pubPem)))
t.Log(signer, err)
if err != nil {
t.Fatal(err)
t.Fail()
}
msg := []byte("123456")
sign, err := signer.Sign(msg)
t.Log(hex.EncodeToString(sign), err)
t.Log(signer.Verify(msg, sign))
}
func TestBadPublicPem(t *testing.T) {
signer, err := crypto.NewSm2(
crypto.ParseSm2PrivateKey([]byte(privPem), []byte{}),
crypto.ParseSm2PublicKey([]byte(badPubPem)))
t.Log(signer, err)
msg := []byte("123456")
sign, err := signer.Sign(msg)
t.Log(hex.EncodeToString(sign), err)
t.Log(signer.Verify(msg, sign))
}
const pemString = `-----BEGIN EC PARAMETERS-----
BggqgRzPVQGCLQ==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIAU/RPiFOw8sI+4dM/0ZusJ7dWxi72DpnOukgGNZfPP5oAoGCCqBHM9V
AYItoUQDQgAEbl5hPO00SJnkTpNjefes6QjmOrhQTrcocBQ0V9yB3ow/COroyHIp
MV8UROLaT5kNUim8Z6XQjL+TWrfo11JQ2w==
-----END EC PRIVATE KEY-----`
func TestDecodePem(t *testing.T) {
block, _ := pem.Decode([]byte(pemString))
fmt.Println(string(block.Bytes))
prv, err := x509.ParseECPrivateKey(block.Bytes)
t.Log(prv, err)
}

81
crypto/sm4.go Normal file
View File

@ -0,0 +1,81 @@
package crypto
import (
"sync"
"github.com/tjfoc/gmsm/sm4"
)
type sm4Instance struct {
key []byte
}
func Sm4(key []byte) *sm4Instance {
return &sm4Instance{key: key}
}
type sm4EcbInstance struct {
*sm4Instance
}
func (o *sm4Instance) ECB() *sm4EcbInstance {
return &sm4EcbInstance{
sm4Instance: o,
}
}
func (o *sm4EcbInstance) Encrypt(msg []byte) ([]byte, error) {
return sm4.Sm4Ecb(o.key, msg, true)
}
func (o *sm4EcbInstance) Decrypt(cipherText []byte) ([]byte, error) {
return sm4.Sm4Ecb(o.key, cipherText, false)
}
type sm4CbcInstance struct {
*sm4Instance
iv []byte
lock sync.Mutex
}
func (o *sm4Instance) CBC() *sm4CbcInstance {
return &sm4CbcInstance{
sm4Instance: o,
}
}
func (o *sm4CbcInstance) WithIV(iv []byte) *sm4CbcInstance {
o.iv = iv
return o
}
func (o *sm4CbcInstance) Encrypt(msg []byte) ([]byte, error) {
o.lock.Lock()
defer o.lock.Unlock()
if err := sm4.SetIV(o.iv); err != nil {
return nil, err
}
defer resetIV()
return sm4.Sm4Cbc(o.key, msg, true)
}
func (o *sm4CbcInstance) Decrypt(cipherText []byte) ([]byte, error) {
o.lock.Lock()
defer o.lock.Unlock()
if err := sm4.SetIV(o.iv); err != nil {
return nil, err
}
defer resetIV()
return sm4.Sm4Cbc(o.key, cipherText, false)
}
var emptyIV = make([]byte, sm4.BlockSize)
func resetIV() {
_ = sm4.SetIV(emptyIV)
}

64
crypto/sm4_test.go Normal file
View File

@ -0,0 +1,64 @@
package crypto_test
import (
"encoding/hex"
"testing"
"github.com/charlienet/go-mixed/crypto"
"github.com/tjfoc/gmsm/sm4"
)
func TestGmsmSm4(t *testing.T) {
key, _ := hex.DecodeString("0123456789ABCDEFFEDCBA9876543210")
msg, _ := hex.DecodeString("F0A2B07E64DD2C2590F93E4EDD90FBB4")
c, err := sm4.Sm4Ecb(key, msg, true)
t.Log(hex.EncodeToString(c), err)
d, err := sm4.Sm4Ecb(key, c, false)
t.Log(hex.EncodeToString(d), err)
}
func TestPadding(t *testing.T) {
msg, _ := hex.DecodeString("F0A2B07E64DD2C2590F93E4EDD90FBB4")
blockSize := sm4.BlockSize
padding := blockSize - len(msg)%blockSize
t.Log(padding)
}
func TestSm4(t *testing.T) {
key := []byte("1234567890abcdef")
msg := []byte("123321123321123321123321123321")
cipherText, err := crypto.Sm4(key).ECB().Encrypt(msg)
t.Log("ECB加密:", hex.EncodeToString(cipherText), err)
de, err := crypto.Sm4(key).ECB().Decrypt(cipherText)
t.Log("ECB解密:", string(de), err)
cipherText, err = crypto.Sm4(key).CBC().WithIV(key).Encrypt(msg)
t.Log("CBC加密:", hex.EncodeToString(cipherText), err)
de, err = crypto.Sm4(key).CBC().WithIV(key).Decrypt(cipherText)
t.Log("CBC解密:", string(de), err)
}
func TestDecrypt(t *testing.T) {
key := []byte("XbBpuLSzaXtlOYFV")
iv := []byte("UISwD9fW6cFh9SNS")
en := "BAD4C05DB0A51895A38D976F97057C2D1743473CE6DABC3456DD4EA751A9794D81096050DBA084F1CB3791C63DFFEDD1D63B046B155FD06386DEE8434A20D8A7465780EF3660ED1073A253DEA4768AB735E2DDEB4602927D3FF85E429C9B7557E6A3A198F4781642CDD30449968FBD2E54E0425E327805DFB0A1DA4FAE33AC68A3377D20042A9459EEF09BEE8CBE483BF61D32B7BB402730AA2276EA3C3A078B895D684A91DD7EEF0F7A25289B1D4905AF524126E8C3DBCB0AB73C92ABC1A83ECA687777B9B609DD8B0F69602EC3E74243E00B33D51EDF930A5316BCB388E4B7B2A6EFDD8B0BE4A19625D297B25D2BD2E5424F2E9B6A4BBF6A70DBE3C6ABB635554AC21CE053D7ECA23D82EF8060C874D507FC27CFCC06EDF41AF98ED0C2C59E39146CC28BA7630D74870BD372863FC4"
c := crypto.Sm4(key).CBC().WithIV(iv)
b, _ := hex.DecodeString(en)
decrypted, err := c.Decrypt(b)
t.Log(hex.EncodeToString(sm4.IV))
t.Log(hex.EncodeToString(decrypted))
t.Log(string(decrypted), err)
encrypted, err := c.Encrypt(decrypted)
t.Log(err)
ddd, err := c.Decrypt(encrypted)
t.Log(string(ddd), err)
}

42
crypto/utils.go Normal file
View File

@ -0,0 +1,42 @@
package crypto
import "crypto"
type Hash uint
const (
MD4 Hash = 1 + iota // import golang.org/x/crypto/md4
MD5 // import crypto/md5
SHA1 // import crypto/sha1
SHA224 // import crypto/sha256
SHA256 // import crypto/sha256
SHA384 // import crypto/sha512
SHA512 // import crypto/sha512
MD5SHA1 // no implementation; MD5+SHA1 used for TLS RSA
RIPEMD160 // import golang.org/x/crypto/ripemd160
SHA3_224 // import golang.org/x/crypto/sha3
SHA3_256 // import golang.org/x/crypto/sha3
SHA3_384 // import golang.org/x/crypto/sha3
SHA3_512 // import golang.org/x/crypto/sha3
SHA512_224 // import crypto/sha512
SHA512_256 // import crypto/sha512
BLAKE2s_256 // import golang.org/x/crypto/blake2s
BLAKE2b_256 // import golang.org/x/crypto/blake2b
BLAKE2b_384 // import golang.org/x/crypto/blake2b
BLAKE2b_512 // import golang.org/x/crypto/blake2b
SM3 // import
)
const (
defaultRsaBits = 1024
)
type hashOptions struct {
h crypto.Hash
}
func (o *hashOptions) getHash(msg []byte) []byte {
h := o.h.New()
h.Write(msg)
return h.Sum(nil)
}