Skip to content

Commit

Permalink
fix bug
Browse files Browse the repository at this point in the history
  • Loading branch information
y-omicron committed Aug 10, 2022
1 parent 11da319 commit c2b8c50
Show file tree
Hide file tree
Showing 5 changed files with 392 additions and 13 deletions.
118 changes: 118 additions & 0 deletions Crypto/Aes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package Crypto

import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"fmt"
"os"
)

type Aes struct {
Key []byte
Iv []byte
}

func (a *Aes) AESGetKey() {
keyIv := make([]byte, 0x20)
_, _ = rand.Read(keyIv)
a.Key = keyIv[:0x10]
a.Iv = keyIv[0x10:]
}
func (a *Aes) String() string {
return base64.StdEncoding.EncodeToString(a.Bytes())
}
func (a *Aes) Bytes() []byte {
return append(a.Key, a.Iv...)
}

// Padding 对明文进行填充
func Padding(plainText []byte, blockSize int) []byte {
//计算要填充的长度
n := blockSize - len(plainText)%blockSize
//对原来的明文填充n个n
temp := bytes.Repeat([]byte{byte(n)}, n)
plainText = append(plainText, temp...)
return plainText
}

// UnPadding 对密文删除填充
func UnPadding(cipherText []byte) []byte {
//取出密文最后一个字节end
end := cipherText[len(cipherText)-1]
//删除填充
cipherText = cipherText[:len(cipherText)-int(end)]
return cipherText
}

// AesCbcEncrypt AEC加密(CBC模式)
func (a *Aes) AesCbcEncrypt(plainText []byte) ([]byte, error) {
//指定加密算法,返回一个AES算法的Block接口对象
block, err := aes.NewCipher(a.Key)
if err != nil {
return nil, err
}
//进行填充
plainText = Padding(plainText, block.BlockSize())
//指定分组模式,返回一个BlockMode接口对象
blockMode := cipher.NewCBCEncrypter(block, a.Iv)
//加密连续数据库
cipherText := make([]byte, len(plainText))
blockMode.CryptBlocks(cipherText, plainText)
//返回密文
return cipherText, nil
}

// AesCbcDecrypt AEC解密(CBC模式)
func (a *Aes) AesCbcDecrypt(cipherText []byte) ([]byte, error) {
//指定解密算法,返回一个AES算法的Block接口对象
block, err := aes.NewCipher(a.Key)
if err != nil {
return nil, err
}
//指定分组模式,返回一个BlockMode接口对象
blockMode := cipher.NewCBCDecrypter(block, a.Iv)
//解密
plainText := make([]byte, len(cipherText))
blockMode.CryptBlocks(plainText, cipherText)
//删除填充
plainText = UnPadding(plainText)
return plainText, nil
}

func (a *Aes) DecryptToFile(cipherText []byte, FilePath string) (int, error) {
// 解密数据
plainText, err := a.AesCbcDecrypt(cipherText)
if err != nil {
return 0, err
}
// 写入文件
return len(plainText), os.WriteFile(FilePath, plainText, 0644)
}

func (a *Aes) EncryptToBase64(plainText []byte) (string, error) {
cbcEncrypt, err := a.AesCbcEncrypt(plainText)
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(cbcEncrypt), nil
}

func TestAes() {
var SelfAes = Aes{}
var Plain = []byte("hello world!")
var Cipher []byte
var err error
SelfAes.AESGetKey()
Cipher, err = SelfAes.AesCbcEncrypt(Plain)
if err != nil {
panic(err)
}
Plain, err = SelfAes.AesCbcDecrypt(Cipher)
if err != nil {
panic(err)
}
fmt.Printf("Cipher: %v\nPlain: %s\n", Cipher, Plain)
}
229 changes: 229 additions & 0 deletions Crypto/Ecc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
package Crypto

import (
"bytes"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"encoding/hex"
"errors"
"fmt"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/ecies"
"io"
"io/ioutil"
"math/big"
"os"
)

type Ecc struct {
EcdsaPrivateKey *ecdsa.PrivateKey
EcdsaPublicKey *ecdsa.PublicKey
EciesPrivateKey *ecies.PrivateKey
EciesPublicKey *ecies.PublicKey
}

// EccGetKey 生成一个ecc(ecdsa)私钥, 并且将其转换为ecc(ecies)私钥
func (e *Ecc) EccGetKey() error {
// 初始化椭圆曲线
PublicCurve := crypto.S256()

// 随机挑选基点,生成私钥
p, err := ecdsa.GenerateKey(PublicCurve, rand.Reader)
if err != nil {
return err
}
e.EcdsaPrivateKey = p

e.EcdsaPublicKey = &e.EcdsaPrivateKey.PublicKey
// 将标准包生成私钥转化为ecies私钥
e.EciesPrivateKey = ecies.ImportECDSA(p)
e.EciesPublicKey = &e.EciesPrivateKey.PublicKey
return nil
}

// ECCEncrypt ecc(ecies)加密
func (e *Ecc) ECCEncrypt(pt []byte) ([]byte, error) {
ct, err := ecies.Encrypt(rand.Reader, e.EciesPublicKey, pt, nil, nil)
return ct, err
}

// ECCDecrypt ecc(ecies)解密
func (e *Ecc) ECCDecrypt(ct []byte) ([]byte, error) {
pt, err := e.EciesPrivateKey.Decrypt(ct, nil, nil)
return pt, err
}

func (e *Ecc) EccSign(pt []byte) (sign []byte, err error) {
// 根据明文plaintext和私钥,生成两个big.Ing
r, s, err := ecdsa.Sign(rand.Reader, e.EcdsaPrivateKey, pt)
if err != nil {
return nil, err
}
rs, err := r.MarshalText()
if err != nil {
return nil, err
}
ss, err := s.MarshalText()
if err != nil {
return nil, err
}
// 将r,s合并(以“+”分割),作为签名返回
var b bytes.Buffer
b.Write(rs)
b.Write([]byte(`+`))
b.Write(ss)
return b.Bytes(), nil
}
func (e *Ecc) EccSignVer(pt, sign []byte) bool {
var rInt, sInt big.Int
// 根据sign,解析出r,s
rs := bytes.Split(sign, []byte("+"))
rInt.UnmarshalText(rs[0])
sInt.UnmarshalText(rs[1])
// 根据公钥,明文,r,s验证签名
v := ecdsa.Verify(e.EcdsaPublicKey, pt, &rInt, &sInt)
return v
}

// GetEcdsaPrivateKey 私钥 -> []byte
func (e *Ecc) GetEcdsaPrivateKey() []byte {
if e.EcdsaPrivateKey == nil {
return nil
}
privy := e.EcdsaPrivateKey
return math.PaddedBigBytes(privy.D, privy.Params().BitSize/8)
}

// SetEcdsaPrivateKey []byte -> 私钥
func (e *Ecc) SetEcdsaPrivateKey(d []byte) (err error) {
e.EcdsaPrivateKey, err = crypto.ToECDSA(d)
e.EcdsaPublicKey = &e.EcdsaPrivateKey.PublicKey
e.EciesPrivateKey = ecies.ImportECDSA(e.EcdsaPrivateKey)
e.EciesPublicKey = &e.EciesPrivateKey.PublicKey
return err
}

// GetEcdsaPublicKey 公钥 -> []byte
func (e *Ecc) GetEcdsaPublicKey() []byte {
pub := &e.EcdsaPrivateKey.PublicKey
if pub == nil || pub.X == nil || pub.Y == nil {
return nil
}
return elliptic.Marshal(crypto.S256(), pub.X, pub.Y)
}

// SetEcdsaPublicKey []byte -> 公钥
func (e *Ecc) SetEcdsaPublicKey(pub []byte) error {
if len(pub) == 0 {
return errors.New("pub len is 0")
}
x, y := elliptic.Unmarshal(crypto.S256(), pub)
e.EcdsaPublicKey = &ecdsa.PublicKey{Curve: crypto.S256(), X: x, Y: y}
e.EciesPublicKey = ecies.ImportECDSAPublic(e.EcdsaPublicKey)
return nil
}

func exKey(prv string) *ecies.PrivateKey {
key, err := crypto.HexToECDSA(prv)
if err != nil {
panic(err)
}
return ecies.ImportECDSA(key)
}

// SaveECDSA 私钥 -> 文件
// SaveECDSA saves a secp256k1 private key to the given file with
// restrictive permissions. The key data is saved hex-encoded.
func (e *Ecc) SaveECDSA(file string) error {
k := hex.EncodeToString(e.GetEcdsaPrivateKey())
return ioutil.WriteFile(file, []byte(k), 0600)
}

// LoadECDSA 文件 -> 私钥
func (e *Ecc) LoadECDSA(file string) error {
buf := make([]byte, 64)
fd, err := os.Open(file)
if err != nil {
return err
}
defer fd.Close()
if _, err := io.ReadFull(fd, buf); err != nil {
return err
}

key, err := hex.DecodeString(string(buf))
if err != nil {
return err
}

return e.SetEcdsaPrivateKey(key)
}
func TestEcc() {
var err error
var SelfEcc = Ecc{}
var YouEcc = Ecc{}
var SignPlain = []byte("yemu")
var SignCipher []byte
var BytesEcdsaPublicKey []byte
var Plain = []byte("hello world!")
var Cipher []byte

// 生成一对 ECC S256 的 key
err = SelfEcc.EccGetKey()
if err != nil {
panic(err)
}
// 导出公钥,并且设置到另一个结构体上
BytesEcdsaPublicKey = SelfEcc.GetEcdsaPublicKey()
fmt.Printf("BytesEcdsaPublicKey: %v\n", BytesEcdsaPublicKey)
err = YouEcc.SetEcdsaPublicKey(BytesEcdsaPublicKey)
if err != nil {
panic(err)
}
// 签名和验签
SignCipher, err = SelfEcc.EccSign(SignPlain)
if err != nil {
panic(err)
}
fmt.Printf("sign: %v\n", YouEcc.EccSignVer(SignPlain, SignCipher))
// 加密与解密
Cipher, err = YouEcc.ECCEncrypt(Plain)
if err != nil {
panic(err)
}
Plain, err = SelfEcc.ECCDecrypt(Cipher)
fmt.Printf("%s\n", Plain)
// 私钥保存
err = SelfEcc.SaveECDSA("ecc.key")
if err != nil {
panic(err)
}
// 私钥读取
var NewEcc = Ecc{}
err = NewEcc.LoadECDSA("ecc.key")
// 公钥设置
var New2Ecc = Ecc{}
err = New2Ecc.SetEcdsaPublicKey([]uint8{4, 136, 76, 169, 50, 219, 86, 251, 42, 210, 193, 174, 161, 229, 226, 177, 94, 177, 86, 1, 224, 132, 80, 145, 168, 124, 130, 66, 176, 5, 140, 186, 73, 19, 226, 205, 234, 10, 44, 65, 8, 108, 205, 64, 2, 157, 63, 5, 79, 184, 110, 225, 197, 187, 78, 255, 27, 83, 169, 209, 3, 146, 211, 130, 230})
if err != nil {
panic(err)
}
// 新的加解密
Cipher, err = New2Ecc.ECCEncrypt(Plain)
if err != nil {
panic(err)
}
Plain, err = NewEcc.ECCDecrypt(Cipher)
if err != nil {
panic(err)
}
fmt.Printf("%s\n", Plain)
// 新的签名验签
SignCipher, err = NewEcc.EccSign(SignPlain)
if err != nil {
panic(err)
}
fmt.Printf("sign: %v\n", New2Ecc.EccSignVer(SignPlain, SignCipher))

}
16 changes: 16 additions & 0 deletions Util/func.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"io/ioutil"
"math/rand"
"os"
"os/exec"
"regexp"
"time"
)
Expand Down Expand Up @@ -110,3 +111,18 @@ func HttpXFileVerify(isFile bool, TagName string, Proxy string, Thread int, out
}
return ret
}
func UnixShell(s string) (string, error) {
//这里是一个小技巧, 以 '/bin/bash -c xx' 的方式调用shell命令, 则可以在命令中使用管道符,组合多个命令
cmd := exec.Command("/bin/sh", "-c", s)
var out bytes.Buffer
cmd.Stdout = &out //把执行命令的标准输出定向到out
cmd.Stderr = &out //把命令的错误输出定向到out

//启动一个子进程执行命令,阻塞到子进程结束退出
err := cmd.Run()
if err != nil {
return "", err
}

return out.String(), err
}
Loading

0 comments on commit c2b8c50

Please sign in to comment.