From 09659fece47b0051a6bb4f597e4be0d66c7b7e66 Mon Sep 17 00:00:00 2001 From: deatil <2217957370@qq.com> Date: Tue, 29 Oct 2024 11:11:50 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=20bign?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cryptobin/bign/bign.go | 84 +++++++ cryptobin/bign/bign_test.go | 438 ++++++++++++++++++++++++++++++++++++ cryptobin/bign/check.go | 22 ++ cryptobin/bign/create.go | 192 ++++++++++++++++ cryptobin/bign/error.go | 17 ++ cryptobin/bign/from.go | 403 +++++++++++++++++++++++++++++++++ cryptobin/bign/get.go | 122 ++++++++++ cryptobin/bign/make.go | 33 +++ cryptobin/bign/on.go | 14 ++ cryptobin/bign/parse.go | 135 +++++++++++ cryptobin/bign/sign.go | 119 ++++++++++ cryptobin/bign/sign_test.go | 189 ++++++++++++++++ cryptobin/bign/to.go | 53 +++++ cryptobin/bign/with.go | 116 ++++++++++ docs/README.md | 1 + docs/bign.md | 131 +++++++++++ docs/ecdsa.md | 2 +- docs/ecgdsa.md | 2 +- pubkey/bign/bign.go | 4 +- pubkey/bign/utils.go | 8 +- 20 files changed, 2077 insertions(+), 8 deletions(-) create mode 100644 cryptobin/bign/bign.go create mode 100644 cryptobin/bign/bign_test.go create mode 100644 cryptobin/bign/check.go create mode 100644 cryptobin/bign/create.go create mode 100644 cryptobin/bign/error.go create mode 100644 cryptobin/bign/from.go create mode 100644 cryptobin/bign/get.go create mode 100644 cryptobin/bign/make.go create mode 100644 cryptobin/bign/on.go create mode 100644 cryptobin/bign/parse.go create mode 100644 cryptobin/bign/sign.go create mode 100644 cryptobin/bign/sign_test.go create mode 100644 cryptobin/bign/to.go create mode 100644 cryptobin/bign/with.go create mode 100644 docs/bign.md diff --git a/cryptobin/bign/bign.go b/cryptobin/bign/bign.go new file mode 100644 index 0000000..d936894 --- /dev/null +++ b/cryptobin/bign/bign.go @@ -0,0 +1,84 @@ +package bign + +import ( + "hash" + "crypto/elliptic" + + "github.com/deatil/go-cryptobin/hash/belt" + "github.com/deatil/go-cryptobin/pubkey/bign" + ecbign "github.com/deatil/go-cryptobin/elliptic/bign" +) + +type ( + // HashFunc + HashFunc = func() hash.Hash +) + +// marshal data type +type EncodingType uint + +const ( + EncodingASN1 EncodingType = 1 + iota + EncodingBytes +) + +/** + * Bign + * + * @create 2024-10-29 + * @author deatil + */ +type Bign struct { + // 私钥 + privateKey *bign.PrivateKey + + // 公钥 + publicKey *bign.PublicKey + + // 生成类型 + curve elliptic.Curve + + // 签名验证类型 + signHash HashFunc + + // 数据编码方式 + encoding EncodingType + + // [私钥/公钥]数据 + keyData []byte + + // 传入数据 + data []byte + + // 传入 adata 数据 + adata []byte + + // 解析后的数据 + parsedData []byte + + // 验证结果 + verify bool + + // 错误 + Errors []error +} + +// 构造函数 +func NewBign() Bign { + return Bign{ + curve: ecbign.P256v1(), + signHash: belt.New, + verify: false, + Errors: make([]error, 0), + } +} + +// 构造函数 +func New() Bign { + return NewBign() +} + +var ( + // 默认 + defaultBign = NewBign() +) diff --git a/cryptobin/bign/bign_test.go b/cryptobin/bign/bign_test.go new file mode 100644 index 0000000..aa08d2c --- /dev/null +++ b/cryptobin/bign/bign_test.go @@ -0,0 +1,438 @@ +package bign + +import ( + "testing" + "crypto/rand" + + cryptobin_test "github.com/deatil/go-cryptobin/tool/test" +) + +func Test_Gen_PKCS1PrivateKey(t *testing.T) { + assertError := cryptobin_test.AssertErrorT(t) + assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) + + gen := GenerateKey("Bign256v1") + assertError(gen.Error(), "Test_Gen_PKCS1PrivateKey") + + priv := gen. + CreatePKCS8PrivateKey(). + ToKeyString() + assertNotEmpty(priv, "Test_Gen_PKCS1PrivateKey-priv") + + pub := gen. + CreatePublicKey(). + ToKeyString() + assertNotEmpty(pub, "Test_Gen_PKCS1PrivateKey-pub") +} + +func Test_Gen_PKCS8PrivateKey(t *testing.T) { + assertError := cryptobin_test.AssertErrorT(t) + assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) + + gen := GenerateKey("Bign256v1") + assertError(gen.Error(), "Test_Gen_PKCS8PrivateKey") + + priv := gen. + CreatePKCS8PrivateKey(). + ToKeyString() + assertNotEmpty(priv, "Test_Gen_PKCS8PrivateKey-priv") + + pub := gen. + CreatePublicKey(). + ToKeyString() + assertNotEmpty(pub, "Test_Gen_PKCS8PrivateKey-pub") +} + +func Test_PublickeyXY(t *testing.T) { + assertError := cryptobin_test.AssertErrorT(t) + assertEqual := cryptobin_test.AssertEqualT(t) + assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) + + obj := GenerateKey("Bign256v1") + + assertError(obj.Error(), "PublickeyXY") + + x := obj.GetPublicKeyUncompressString() + xx := obj.GetPublicKeyCompressString() + + assertNotEmpty(x, "PublickeyXY-x") + assertNotEmpty(xx, "PublickeyXY-xx") + + xk := New().SetCurve("Bign256v1").FromPublicKeyUncompressString(x) + xxk := New().SetCurve("Bign256v1").FromPublicKeyCompressString(xx) + + assertError(xk.Error(), "PublickeyXY-xk") + assertError(xxk.Error(), "PublickeyXY-xxk") + + assertEqual(xk.GetPublicKey(), obj.GetPublicKey(), "PublickeyXY-xk") + assertEqual(xxk.GetPublicKey(), obj.GetPublicKey(), "PublickeyXY-xxk") + +} + +func Test_PublickeyXY_2(t *testing.T) { + assertError := cryptobin_test.AssertErrorT(t) + assertEqual := cryptobin_test.AssertEqualT(t) + assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) + + obj := GenerateKey("Bign256v1") + + assertError(obj.Error(), "PublickeyXY") + + x := obj.GetPublicKeyUncompressString() + xx := obj.GetPublicKeyCompressString() + + assertNotEmpty(x, "PublickeyXY-x") + assertNotEmpty(xx, "PublickeyXY-xx") + + xk := New().SetCurve("Bign256v1").FromPublicKeyString(x) + xxk := New().SetCurve("Bign256v1").FromPublicKeyString(xx) + + assertError(xk.Error(), "PublickeyXY-xk") + assertError(xxk.Error(), "PublickeyXY-xxk") + + assertEqual(xk.GetPublicKey(), obj.GetPublicKey(), "PublickeyXY-xk") + assertEqual(xxk.GetPublicKey(), obj.GetPublicKey(), "PublickeyXY-xxk") + +} + +func Test_PublickeyXY_String(t *testing.T) { + assertError := cryptobin_test.AssertErrorT(t) + assertEqual := cryptobin_test.AssertEqualT(t) + assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) + + obj := GenerateKey("Bign256v1") + + assertError(obj.Error(), "PublickeyXY_3") + + x := obj.GetPublicKeyXString() + y := obj.GetPublicKeyYString() + + assertNotEmpty(x, "PublickeyXY_3-x") + assertNotEmpty(y, "PublickeyXY_3-y") + + xk := New().SetCurve("Bign256v1").FromPublicKeyXYString(x, y) + + assertError(xk.Error(), "PublickeyXY_3-xk") + assertEqual(xk.GetPublicKey(), obj.GetPublicKey(), "PublickeyXY_3-xk") +} + +func Test_PublickeyXY_Bytes(t *testing.T) { + assertError := cryptobin_test.AssertErrorT(t) + assertEqual := cryptobin_test.AssertEqualT(t) + assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) + + obj := GenerateKey("Bign256v1") + + assertError(obj.Error(), "PublickeyXY_Bytes") + + pub := obj.GetPublicKey() + + x := pub.X.Bytes() + y := pub.Y.Bytes() + + assertNotEmpty(x, "PublickeyXY_Bytes-x") + assertNotEmpty(y, "PublickeyXY_Bytes-y") + + xk := New().SetCurve("Bign256v1").FromPublicKeyXYBytes(x, y) + + assertError(xk.Error(), "PublickeyXY_Bytes-xk") + assertEqual(xk.GetPublicKey(), obj.GetPublicKey(), "PublickeyXY_Bytes-xk") +} + +func Test_PrivateKeyD(t *testing.T) { + assertError := cryptobin_test.AssertErrorT(t) + assertEqual := cryptobin_test.AssertEqualT(t) + assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) + + obj := GenerateKey("Bign256v1") + + assertError(obj.Error(), "PrivateKeyD") + + d := obj.GetPrivateKeyString() + + assertNotEmpty(d, "PrivateKeyD") + + xk := New().SetCurve("Bign256v1").FromPrivateKeyString(d) + + assertError(xk.Error(), "PrivateKeyD-xk") + + assertEqual(xk.GetPrivateKey(), obj.GetPrivateKey(), "PrivateKeyD-xk") +} + +func Test_PrivateKey_Bytes(t *testing.T) { + assertError := cryptobin_test.AssertErrorT(t) + assertEqual := cryptobin_test.AssertEqualT(t) + assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) + + obj := GenerateKey("Bign256v1") + + assertError(obj.Error(), "PrivateKeyD") + + priv := obj.GetPrivateKey() + + d := priv.D.Bytes() + + assertNotEmpty(d, "PrivateKey_Bytes") + + xk := New().SetCurve("Bign256v1").FromPrivateKeyBytes(d) + + assertError(xk.Error(), "PrivateKey_Bytes-xk") + + assertEqual(xk.GetPrivateKey(), obj.GetPrivateKey(), "PrivateKey_Bytes-xk") +} + +func Test_GetPrivateKeyString(t *testing.T) { + assertError := cryptobin_test.AssertErrorT(t) + assertEqual := cryptobin_test.AssertEqualT(t) + assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) + + obj := GenerateKey("Bign256v1") + assertError(obj.Error(), "GetPrivateKeyString") + + priv := obj.GetPrivateKeyString() + assertNotEmpty(priv, "GetPrivateKeyString") + + xk := New().SetCurve("Bign256v1").FromPrivateKeyString(priv) + + assertError(xk.Error(), "GetPrivateKeyString-xk") + assertEqual(xk.GetPrivateKey(), obj.GetPrivateKey(), "GetPrivateKeyString-xk") +} + +var testPEMCiphers = []string{ + "DESCBC", + "DESEDE3CBC", + "AES128CBC", + "AES192CBC", + "AES256CBC", + + "DESCFB", + "DESEDE3CFB", + "AES128CFB", + "AES192CFB", + "AES256CFB", + + "DESOFB", + "DESEDE3OFB", + "AES128OFB", + "AES192OFB", + "AES256OFB", + + "DESCTR", + "DESEDE3CTR", + "AES128CTR", + "AES192CTR", + "AES256CTR", +} + +func Test_CreatePKCS1PrivateKeyWithPassword(t *testing.T) { + for _, cipher := range testPEMCiphers{ + test_CreatePKCS1PrivateKeyWithPassword(t, cipher) + } +} + +func test_CreatePKCS1PrivateKeyWithPassword(t *testing.T, cipher string) { + assertEqual := cryptobin_test.AssertEqualT(t) + assertError := cryptobin_test.AssertErrorT(t) + assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) + + t.Run(cipher, func(t *testing.T) { + pass := make([]byte, 12) + _, err := rand.Read(pass) + if err != nil { + t.Fatal(err) + } + + gen := New().GenerateKey() + + prikey := gen.GetPrivateKey() + + pri := gen. + CreatePKCS1PrivateKeyWithPassword(string(pass), cipher). + ToKeyString() + + assertError(gen.Error(), "Test_CreatePKCS1PrivateKeyWithPassword") + assertNotEmpty(pri, "Test_CreatePKCS1PrivateKeyWithPassword-pri") + + newPrikey := New(). + FromPKCS1PrivateKeyWithPassword([]byte(pri), string(pass)). + GetPrivateKey() + + assertNotEmpty(newPrikey, "Test_CreatePKCS1PrivateKeyWithPassword-newPrikey") + + assertEqual(newPrikey, prikey, "Test_CreatePKCS1PrivateKeyWithPassword") + }) +} + +func Test_PKCS8PrivateKey_Der(t *testing.T) { + assertError := cryptobin_test.AssertErrorT(t) + assertEqual := cryptobin_test.AssertEqualT(t) + assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) + + obj := GenerateKey("Bign256v1") + assertError(obj.Error(), "PKCS8PrivateKey_Der") + + privDer := obj. + CreatePKCS8PrivateKey(). + MakeKeyDer(). + ToKeyBytes() + assertNotEmpty(privDer, "PKCS8PrivateKey_Der-der") + + res := New(). + SetCurve("Bign256v1"). + FromPKCS8PrivateKeyDer(privDer) + assertError(res.Error(), "PKCS8PrivateKey_Der-res") + + assertEqual(res.GetPrivateKey(), obj.GetPrivateKey(), "PKCS8PrivateKey_Der-res") +} + +func Test_PKCS1PrivateKey_Der(t *testing.T) { + assertError := cryptobin_test.AssertErrorT(t) + assertEqual := cryptobin_test.AssertEqualT(t) + assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) + + obj := GenerateKey("Bign256v1") + assertError(obj.Error(), "PKCS1PrivateKey_Der") + + privDer := obj. + CreatePKCS1PrivateKey(). + MakeKeyDer(). + ToKeyBytes() + assertNotEmpty(privDer, "PKCS1PrivateKey_Der-der") + + res := New(). + SetCurve("Bign256v1"). + FromPKCS1PrivateKeyDer(privDer) + assertError(res.Error(), "PKCS1PrivateKey_Der-res") + + assertEqual(res.GetPrivateKey(), obj.GetPrivateKey(), "PKCS1PrivateKey_Der-res") +} + +func Test_PublicKey_Der(t *testing.T) { + assertError := cryptobin_test.AssertErrorT(t) + assertEqual := cryptobin_test.AssertEqualT(t) + assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) + + obj := GenerateKey("Bign256v1") + assertError(obj.Error(), "PublicKey_Der") + + privDer := obj. + CreatePublicKey(). + MakeKeyDer(). + ToKeyBytes() + assertNotEmpty(privDer, "PublicKey_Der-der") + + res := New(). + SetCurve("Bign256v1"). + FromPublicKeyDer(privDer) + assertError(res.Error(), "PublicKey_Der-res") + + assertEqual(res.GetPublicKey(), obj.GetPublicKey(), "PublicKey_Der-res") +} + +func Test_EncodingType(t *testing.T) { + assertEqual := cryptobin_test.AssertEqualT(t) + + var ecdsa Bign + + ecdsa = NewBign().WithEncoding(EncodingASN1) + assertEqual(ecdsa.encoding, EncodingASN1, "EncodingASN1 1") + + ecdsa = NewBign().WithEncodingASN1() + assertEqual(ecdsa.encoding, EncodingASN1, "EncodingASN1") + + ecdsa = NewBign().WithEncodingBytes() + assertEqual(ecdsa.encoding, EncodingBytes, "EncodingBytes") + + ecdsa = Bign{ + encoding: EncodingASN1, + } + assertEqual(ecdsa.GetEncoding(), EncodingASN1, "new EncodingASN1") + + ecdsa = Bign{ + encoding: EncodingBytes, + } + assertEqual(ecdsa.GetEncoding(), EncodingBytes, "new EncodingBytes") +} + +func Test_SignWithEncoding(t *testing.T) { + t.Run("EncodingASN1", func(t *testing.T) { + test_SignWithEncoding(t, EncodingASN1) + }) + + t.Run("EncodingBytes", func(t *testing.T) { + test_SignWithEncoding(t, EncodingBytes) + }) +} + +func test_SignWithEncoding(t *testing.T, encoding EncodingType) { + assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) + assertBool := cryptobin_test.AssertBoolT(t) + assertError := cryptobin_test.AssertErrorT(t) + + gen := GenerateKey("Bign256v1") + + data := "test-pass" + adata := []byte{ + 0x00, 0x0b, 0x00, 0x00, + 0x06, 0x09, 0x2A, 0x70, 0x00, 0x02, 0x00, 0x22, 0x65, 0x1F, 0x51, + } + + // 签名 + objSign := gen. + FromString(data). + WithAdata(adata). + WithEncoding(encoding). + Sign() + signed := objSign.ToBase64String() + + assertError(objSign.Error(), "test_SignWithEncoding-Sign") + assertNotEmpty(signed, "test_SignWithEncoding-Sign") + + // 验证 + objVerify := gen. + FromBase64String(signed). + WithAdata(adata). + WithEncoding(encoding). + Verify([]byte(data)) + + assertError(objVerify.Error(), "test_SignWithEncoding-Verify") + assertBool(objVerify.ToVerify(), "test_SignWithEncoding-Verify") +} + +func Test_SignWithEncoding_Two_Check(t *testing.T) { + assertError := cryptobin_test.AssertErrorT(t) + assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) + assertNotEqual := cryptobin_test.AssertNotEqualT(t) + + data := "test-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-passtest-pass" + adata := []byte{ + 0x00, 0x0b, 0x00, 0x00, + 0x06, 0x09, 0x2A, 0x70, 0x00, 0x02, 0x00, 0x22, 0x65, 0x1F, 0x51, + } + + gen := GenerateKey("Bign256v1") + + // 签名 + objSign := gen. + FromString(data). + WithAdata(adata). + WithEncoding(EncodingASN1). + Sign() + signed := objSign.ToBase64String() + + assertError(objSign.Error(), "Test_SignWithEncoding_Two_Check-Sign") + assertNotEmpty(signed, "Test_SignWithEncoding_Two_Check-Sign") + + // 签名 + objSign2 := gen. + FromString(data). + WithAdata(adata). + WithEncoding(EncodingBytes). + Sign() + signed2 := objSign2.ToBase64String() + + assertError(objSign2.Error(), "Test_SignWithEncoding_Two_Check-Sign") + assertNotEmpty(signed2, "Test_SignWithEncoding_Two_Check-Sign") + + assertNotEqual(signed2, signed, "Test_SignWithEncoding_Two_Check") +} diff --git a/cryptobin/bign/check.go b/cryptobin/bign/check.go new file mode 100644 index 0000000..34be0e5 --- /dev/null +++ b/cryptobin/bign/check.go @@ -0,0 +1,22 @@ +package bign + +// 检测公钥私钥是否匹配 +func (this Bign) CheckKeyPair() bool { + // 私钥导出的公钥 + pubKeyFromPriKey := this.MakePublicKey(). + CreatePublicKey(). + ToKeyString() + + // 公钥数据 + pubKeyFromPubKey := this.CreatePublicKey().ToKeyString() + + if pubKeyFromPriKey == "" || pubKeyFromPubKey == "" { + return false + } + + if pubKeyFromPriKey == pubKeyFromPubKey { + return true + } + + return false +} diff --git a/cryptobin/bign/create.go b/cryptobin/bign/create.go new file mode 100644 index 0000000..7595da7 --- /dev/null +++ b/cryptobin/bign/create.go @@ -0,0 +1,192 @@ +package bign + +import ( + "errors" + "crypto/rand" + "encoding/pem" + + "github.com/deatil/go-cryptobin/pkcs1" + "github.com/deatil/go-cryptobin/pkcs8" + "github.com/deatil/go-cryptobin/pubkey/bign" +) + +type ( + // 配置 + Opts = pkcs8.Opts + // PBKDF2 配置 + PBKDF2Opts = pkcs8.PBKDF2Opts + // Scrypt 配置 + ScryptOpts = pkcs8.ScryptOpts +) + +var ( + // 获取 Cipher 类型 + GetCipherFromName = pkcs8.GetCipherFromName + // 获取 hash 类型 + GetHashFromName = pkcs8.GetHashFromName +) + +// 生成私钥 pem 数据, PKCS1 别名 +// 使用: +// gen := GenerateKey("P521") +// priKey := gen.CreatePrivateKey().ToKeyString() +func (this Bign) CreatePrivateKey() Bign { + return this.CreatePKCS1PrivateKey() +} + +// 生成私钥带密码 pem 数据, PKCS1 别名 +// CreatePrivateKeyWithPassword("123", "AES256CBC") +// PEMCipher: DESCBC | DESEDE3CBC | AES128CBC | AES192CBC | AES256CBC +func (this Bign) CreatePrivateKeyWithPassword(password string, opts ...string) Bign { + return this.CreatePKCS1PrivateKeyWithPassword(password, opts...) +} + +// ==================== + +// 生成私钥 pem 数据 +func (this Bign) CreatePKCS1PrivateKey() Bign { + if this.privateKey == nil { + err := errors.New("privateKey empty.") + return this.AppendError(err) + } + + publicKeyBytes, err := bign.MarshalECPrivateKey(this.privateKey) + if err != nil { + return this.AppendError(err) + } + + privateBlock := &pem.Block{ + Type: "Bign PRIVATE KEY", + Bytes: publicKeyBytes, + } + + this.keyData = pem.EncodeToMemory(privateBlock) + + return this +} + +// 生成私钥带密码 pem 数据 +func (this Bign) CreatePKCS1PrivateKeyWithPassword(password string, opts ...string) Bign { + if this.privateKey == nil { + err := errors.New("privateKey empty.") + return this.AppendError(err) + } + + opt := "AES256CBC" + if len(opts) > 0 { + opt = opts[0] + } + + // 加密方式 + cipher := pkcs1.GetPEMCipher(opt) + if cipher == nil { + err := errors.New("PEMCipher not exists.") + return this.AppendError(err) + } + + // 生成私钥 + publicKeyBytes, err := bign.MarshalECPrivateKey(this.privateKey) + if err != nil { + return this.AppendError(err) + } + + // 生成加密数据 + privateBlock, err := pkcs1.EncryptPEMBlock( + rand.Reader, + "Bign PRIVATE KEY", + publicKeyBytes, + []byte(password), + cipher, + ) + if err != nil { + return this.AppendError(err) + } + + this.keyData = pem.EncodeToMemory(privateBlock) + + return this +} + +// ==================== + +// 生成 PKCS8 私钥 pem 数据 +func (this Bign) CreatePKCS8PrivateKey() Bign { + if this.privateKey == nil { + err := errors.New("privateKey empty.") + return this.AppendError(err) + } + + publicKeyBytes, err := bign.MarshalPrivateKey(this.privateKey) + if err != nil { + return this.AppendError(err) + } + + privateBlock := &pem.Block{ + Type: "PRIVATE KEY", + Bytes: publicKeyBytes, + } + + this.keyData = pem.EncodeToMemory(privateBlock) + + return this +} + +// 生成 PKCS8 私钥带密码 pem 数据 +// CreatePKCS8PrivateKeyWithPassword("123", "AES256CBC", "SHA256") +func (this Bign) CreatePKCS8PrivateKeyWithPassword(password string, opts ...any) Bign { + if this.privateKey == nil { + err := errors.New("privateKey empty.") + return this.AppendError(err) + } + + opt, err := pkcs8.ParseOpts(opts...) + if err != nil { + return this.AppendError(err) + } + + // 生成私钥 + publicKeyBytes, err := bign.MarshalPrivateKey(this.privateKey) + if err != nil { + return this.AppendError(err) + } + + // 生成加密数据 + privateBlock, err := pkcs8.EncryptPEMBlock( + rand.Reader, + "ENCRYPTED PRIVATE KEY", + publicKeyBytes, + []byte(password), + opt, + ) + if err != nil { + return this.AppendError(err) + } + + this.keyData = pem.EncodeToMemory(privateBlock) + + return this +} + +// ==================== + +// 生成公钥 pem 数据 +func (this Bign) CreatePublicKey() Bign { + if this.publicKey == nil { + err := errors.New("publicKey empty.") + return this.AppendError(err) + } + + publicKeyBytes, err := bign.MarshalPublicKey(this.publicKey) + if err != nil { + return this.AppendError(err) + } + + publicBlock := &pem.Block{ + Type: "PUBLIC KEY", + Bytes: publicKeyBytes, + } + + this.keyData = pem.EncodeToMemory(publicBlock) + + return this +} diff --git a/cryptobin/bign/error.go b/cryptobin/bign/error.go new file mode 100644 index 0000000..c803749 --- /dev/null +++ b/cryptobin/bign/error.go @@ -0,0 +1,17 @@ +package bign + +import ( + "github.com/deatil/go-cryptobin/tool" +) + +// 添加错误 +func (this Bign) AppendError(err ...error) Bign { + this.Errors = append(this.Errors, err...) + + return this +} + +// 获取错误 +func (this Bign) Error() error { + return tool.NewError(this.Errors...) +} diff --git a/cryptobin/bign/from.go b/cryptobin/bign/from.go new file mode 100644 index 0000000..b7b3445 --- /dev/null +++ b/cryptobin/bign/from.go @@ -0,0 +1,403 @@ +package bign + +import ( + "io" + "errors" + "math/big" + "crypto/rand" + "crypto/elliptic" + + "github.com/deatil/go-cryptobin/tool" + "github.com/deatil/go-cryptobin/pubkey/bign" +) + +// 生成密钥 +func (this Bign) GenerateKeyWithSeed(reader io.Reader) Bign { + privateKey, err := bign.GenerateKey(reader, this.curve) + if err != nil { + return this.AppendError(err) + } + + this.privateKey = privateKey + this.publicKey = &privateKey.PublicKey + + return this +} + +// 生成密钥 +// 可选 [Bign256v1 | Bign384v1 | Bign512v1] +func GenerateKeyWithSeed(reader io.Reader, curve string) Bign { + return defaultBign.SetCurve(curve).GenerateKeyWithSeed(reader) +} + +// 生成密钥 +func (this Bign) GenerateKey() Bign { + return this.GenerateKeyWithSeed(rand.Reader) +} + +// 生成密钥 +// 可选 [Bign256v1 | Bign384v1 | Bign512v1] +func GenerateKey(curve string) Bign { + return defaultBign.SetCurve(curve).GenerateKey() +} + +// ========== + +// 私钥 +func (this Bign) FromPrivateKey(key []byte) Bign { + privateKey, err := this.ParsePKCS8PrivateKeyFromPEM(key) + if err == nil { + this.privateKey = privateKey + + return this + } + + privateKey, err = this.ParsePKCS1PrivateKeyFromPEM(key) + if err != nil { + return this.AppendError(err) + } + + this.privateKey = privateKey + + return this +} + +// 私钥 +func FromPrivateKey(key []byte) Bign { + return defaultBign.FromPrivateKey(key) +} + +// 私钥带密码 +func (this Bign) FromPrivateKeyWithPassword(key []byte, password string) Bign { + privateKey, err := this.ParsePKCS8PrivateKeyFromPEMWithPassword(key, password) + if err == nil { + this.privateKey = privateKey + + return this + } + + privateKey, err = this.ParsePKCS1PrivateKeyFromPEMWithPassword(key, password) + if err != nil { + return this.AppendError(err) + } + + this.privateKey = privateKey + + return this +} + +// 私钥 +func FromPrivateKeyWithPassword(key []byte, password string) Bign { + return defaultBign.FromPrivateKeyWithPassword(key, password) +} + +// ========== + +// 私钥 +func (this Bign) FromPKCS1PrivateKey(key []byte) Bign { + privateKey, err := this.ParsePKCS1PrivateKeyFromPEM(key) + if err != nil { + return this.AppendError(err) + } + + this.privateKey = privateKey + + return this +} + +// 私钥 +func FromPKCS1PrivateKey(key []byte) Bign { + return defaultBign.FromPKCS1PrivateKey(key) +} + +// 私钥带密码 +func (this Bign) FromPKCS1PrivateKeyWithPassword(key []byte, password string) Bign { + privateKey, err := this.ParsePKCS1PrivateKeyFromPEMWithPassword(key, password) + if err != nil { + return this.AppendError(err) + } + + this.privateKey = privateKey + + return this +} + +// 私钥带密码 +func FromPKCS1PrivateKeyWithPassword(key []byte, password string) Bign { + return defaultBign.FromPKCS1PrivateKeyWithPassword(key, password) +} + +// ========== + +// PKCS8 私钥 +func (this Bign) FromPKCS8PrivateKey(key []byte) Bign { + privateKey, err := this.ParsePKCS8PrivateKeyFromPEM(key) + if err != nil { + return this.AppendError(err) + } + + this.privateKey = privateKey + + return this +} + +// PKCS8 私钥 +func FromPKCS8PrivateKey(key []byte) Bign { + return defaultBign.FromPKCS8PrivateKey(key) +} + +// Pkcs8WithPassword +func (this Bign) FromPKCS8PrivateKeyWithPassword(key []byte, password string) Bign { + privateKey, err := this.ParsePKCS8PrivateKeyFromPEMWithPassword(key, password) + if err != nil { + return this.AppendError(err) + } + + this.privateKey = privateKey + + return this +} + +// PKCS8 私钥带密码 +func FromPKCS8PrivateKeyWithPassword(key []byte, password string) Bign { + return defaultBign.FromPKCS8PrivateKeyWithPassword(key, password) +} + +// ========== + +// 公钥 +func (this Bign) FromPublicKey(key []byte) Bign { + publicKey, err := this.ParsePublicKeyFromPEM(key) + if err != nil { + return this.AppendError(err) + } + + this.publicKey = publicKey + + return this +} + +// 公钥 +func FromPublicKey(key []byte) Bign { + return defaultBign.FromPublicKey(key) +} + +// ========== + +// DER 私钥 +func (this Bign) FromPKCS1PrivateKeyDer(der []byte) Bign { + key := tool.EncodeDerToPem(der, "Bign PRIVATE KEY") + + privateKey, err := this.ParsePKCS1PrivateKeyFromPEM(key) + if err != nil { + return this.AppendError(err) + } + + this.privateKey = privateKey + + return this +} + +// DER 私钥 +func (this Bign) FromPKCS8PrivateKeyDer(der []byte) Bign { + key := tool.EncodeDerToPem(der, "PRIVATE KEY") + + privateKey, err := this.ParsePKCS8PrivateKeyFromPEM(key) + if err != nil { + return this.AppendError(err) + } + + this.privateKey = privateKey + + return this +} + +// DER 公钥 +func (this Bign) FromPublicKeyDer(der []byte) Bign { + key := tool.EncodeDerToPem(der, "PUBLIC KEY") + + publicKey, err := this.ParsePublicKeyFromPEM(key) + if err != nil { + return this.AppendError(err) + } + + this.publicKey = publicKey + + return this +} + +// ========== + +// 公钥 x,y 16进制字符对 +// 需要设置对应的 curve +// [xString: xHexString, yString: yHexString] +func (this Bign) FromPublicKeyXYString(xString string, yString string) Bign { + x, _ := new(big.Int).SetString(xString[:], 16) + y, _ := new(big.Int).SetString(yString[:], 16) + + this.publicKey = &bign.PublicKey{ + Curve: this.curve, + X: x, + Y: y, + } + + return this +} + +// 公钥字符对,需要设置对应的 curve +func (this Bign) FromPublicKeyXYBytes(xBytes, yBytes []byte) Bign { + x := new(big.Int).SetBytes(xBytes) + y := new(big.Int).SetBytes(yBytes) + + this.publicKey = &bign.PublicKey{ + Curve: this.curve, + X: x, + Y: y, + } + + return this +} + +// ========== + +// 公钥明文未压缩 +// 需要设置对应的 curve +// public-key hex: 047c********. +func (this Bign) FromPublicKeyUncompressString(key string) Bign { + k, _ := tool.HexDecode(key) + + x, y := elliptic.Unmarshal(this.curve, k) + if x == nil || y == nil { + err := errors.New("publicKey uncompress string error") + + return this.AppendError(err) + } + + this.publicKey = &bign.PublicKey{ + Curve: this.curve, + X: x, + Y: y, + } + + return this +} + +// 公钥明文压缩 +// 需要设置对应的 curve +// public-key hex: 027c******** || 036c******** +func (this Bign) FromPublicKeyCompressString(key string) Bign { + k, _ := tool.HexDecode(key) + + x, y := elliptic.UnmarshalCompressed(this.curve, k) + if x == nil || y == nil { + err := errors.New("publicKey compress string error") + + return this.AppendError(err) + } + + this.publicKey = &bign.PublicKey{ + Curve: this.curve, + X: x, + Y: y, + } + + return this +} + +// 公钥明文,需要设置对应的 curve +func (this Bign) FromPublicKeyString(key string) Bign { + byteLen := (this.curve.Params().BitSize + 7) / 8 + + k, _ := tool.HexDecode(key) + + if len(k) == 1+byteLen { + return this.FromPublicKeyCompressString(key) + } + + return this.FromPublicKeyUncompressString(key) +} + +// 私钥明文,需要设置对应的 curve +// private-key: 07e4********; +func (this Bign) FromPrivateKeyString(keyString string) Bign { + k, _ := new(big.Int).SetString(keyString, 16) + + return this.FromPrivateKeyBytes(k.Bytes()) +} + +// ========== + +// 公钥明文, hex 或者 base64 解码后 +// 需要设置对应的 curve +func (this Bign) FromPublicKeyBytes(pub []byte) Bign { + key := tool.HexEncode(pub) + + return this.FromPublicKeyString(key) +} + +// 明文私钥生成私钥结构体 +// 需要设置对应的 curve +func (this Bign) FromPrivateKeyBytes(priByte []byte) Bign { + priv, err := bign.NewPrivateKey(this.curve, priByte) + if err != nil { + return this.AppendError(err) + } + + this.privateKey = priv + + return this +} + +// ========== + +// 字节 +func (this Bign) FromBytes(data []byte) Bign { + this.data = data + + return this +} + +// 字节 +func FromBytes(data []byte) Bign { + return defaultBign.FromBytes(data) +} + +// 字符 +func (this Bign) FromString(data string) Bign { + this.data = []byte(data) + + return this +} + +// 字符 +func FromString(data string) Bign { + return defaultBign.FromString(data) +} + +// Base64 +func (this Bign) FromBase64String(data string) Bign { + newData, err := tool.Base64Decode(data) + + this.data = newData + + return this.AppendError(err) +} + +// Base64 +func FromBase64String(data string) Bign { + return defaultBign.FromBase64String(data) +} + +// Hex +func (this Bign) FromHexString(data string) Bign { + newData, err := tool.HexDecode(data) + + this.data = newData + + return this.AppendError(err) +} + +// Hex +func FromHexString(data string) Bign { + return defaultBign.FromHexString(data) +} diff --git a/cryptobin/bign/get.go b/cryptobin/bign/get.go new file mode 100644 index 0000000..e0830ba --- /dev/null +++ b/cryptobin/bign/get.go @@ -0,0 +1,122 @@ +package bign + +import ( + "crypto/elliptic" + + "github.com/deatil/go-cryptobin/tool" + "github.com/deatil/go-cryptobin/pubkey/bign" +) + +// get PrivateKey +func (this Bign) GetPrivateKey() *bign.PrivateKey { + return this.privateKey +} + +// get PrivateKey Curve +func (this Bign) GetPrivateKeyCurve() elliptic.Curve { + return this.privateKey.Curve +} + +// get PrivateKey D hex string +func (this Bign) GetPrivateKeyDString() string { + data := this.privateKey.D + + return tool.HexEncode(data.Bytes()) +} + +// get PrivateKey data hex string +func (this Bign) GetPrivateKeyString() string { + priv := bign.PrivateKeyTo(this.privateKey) + + return tool.HexEncode(priv) +} + +// get PublicKey +func (this Bign) GetPublicKey() *bign.PublicKey { + return this.publicKey +} + +// get PublicKey Curve +func (this Bign) GetPublicKeyCurve() elliptic.Curve { + return this.publicKey.Curve +} + +// get PublicKey X hex string +func (this Bign) GetPublicKeyXString() string { + x := this.publicKey.X + + return tool.HexEncode(x.Bytes()) +} + +// get PublicKey Y hex string +func (this Bign) GetPublicKeyYString() string { + y := this.publicKey.Y + + return tool.HexEncode(y.Bytes()) +} + +// get PublicKey X and Y Hex string +func (this Bign) GetPublicKeyXYString() string { + key := elliptic.Marshal(this.publicKey.Curve, this.publicKey.X, this.publicKey.Y) + + return tool.HexEncode(key[1:]) +} + +// get PublicKey Uncompress Hex string +func (this Bign) GetPublicKeyUncompressString() string { + key := elliptic.Marshal(this.publicKey.Curve, this.publicKey.X, this.publicKey.Y) + + return tool.HexEncode(key) +} + +// get PublicKey Compress Hex string +func (this Bign) GetPublicKeyCompressString() string { + key := elliptic.MarshalCompressed(this.publicKey.Curve, this.publicKey.X, this.publicKey.Y) + + return tool.HexEncode(key) +} + +// get Curve +func (this Bign) GetCurve() elliptic.Curve { + return this.curve +} + +// get signHash type +func (this Bign) GetSignHash() HashFunc { + return this.signHash +} + +// get keyData +func (this Bign) GetKeyData() []byte { + return this.keyData +} + +// get data +func (this Bign) GetData() []byte { + return this.data +} + +// get adata +func (this Bign) GetAdata() []byte { + return this.adata +} + +// get parsedData +func (this Bign) GetParsedData() []byte { + return this.parsedData +} + +// get Encoding type +func (this Bign) GetEncoding() EncodingType { + return this.encoding +} + +// get verify data +func (this Bign) GetVerify() bool { + return this.verify +} + +// get errors +func (this Bign) GetErrors() []error { + return this.Errors +} diff --git a/cryptobin/bign/make.go b/cryptobin/bign/make.go new file mode 100644 index 0000000..b26d44b --- /dev/null +++ b/cryptobin/bign/make.go @@ -0,0 +1,33 @@ +package bign + +import( + "errors" + "encoding/pem" +) + +// 生成公钥 +func (this Bign) MakePublicKey() Bign { + this.publicKey = nil + + if this.privateKey == nil { + err := errors.New("privateKey empty.") + return this.AppendError(err) + } + + this.publicKey = &this.privateKey.PublicKey + + return this +} + +// 生成密钥 der 数据 +func (this Bign) MakeKeyDer() Bign { + var block *pem.Block + if block, _ = pem.Decode(this.keyData); block == nil { + err := errors.New("keyData error.") + return this.AppendError(err) + } + + this.keyData = block.Bytes + + return this +} diff --git a/cryptobin/bign/on.go b/cryptobin/bign/on.go new file mode 100644 index 0000000..6dc22ea --- /dev/null +++ b/cryptobin/bign/on.go @@ -0,0 +1,14 @@ +package bign + +type ( + // 错误方法 + EcgdsaErrorFunc = func([]error) +) + +// 引出错误信息 +func (this Bign) OnError(fn EcgdsaErrorFunc) Bign { + fn(this.Errors) + + return this +} + diff --git a/cryptobin/bign/parse.go b/cryptobin/bign/parse.go new file mode 100644 index 0000000..165b744 --- /dev/null +++ b/cryptobin/bign/parse.go @@ -0,0 +1,135 @@ +package bign + +import ( + "errors" + "crypto/x509" + "encoding/pem" + + "github.com/deatil/go-cryptobin/pkcs1" + "github.com/deatil/go-cryptobin/pkcs8" + "github.com/deatil/go-cryptobin/pubkey/bign" +) + +var ( + ErrKeyMustBePEMEncoded = errors.New("invalid key: Key must be a PEM encoded PKCS1 or PKCS8 key") + ErrNotECPublicKey = errors.New("key is not a valid Bign public key") +) + +// 解析私钥 +func (this Bign) ParsePKCS1PrivateKeyFromPEM(key []byte) (*bign.PrivateKey, error) { + var err error + + // Parse PEM block + var block *pem.Block + if block, _ = pem.Decode(key); block == nil { + return nil, ErrKeyMustBePEMEncoded + } + + // Parse the key + var pkey *bign.PrivateKey + if pkey, err = bign.ParseECPrivateKey(block.Bytes); err != nil { + return nil, err + } + + return pkey, nil +} + +// 解析私钥带密码 +func (this Bign) ParsePKCS1PrivateKeyFromPEMWithPassword(key []byte, password string) (*bign.PrivateKey, error) { + var err error + + // Parse PEM block + var block *pem.Block + if block, _ = pem.Decode(key); block == nil { + return nil, ErrKeyMustBePEMEncoded + } + + var blockDecrypted []byte + if blockDecrypted, err = pkcs1.DecryptPEMBlock(block, []byte(password)); err != nil { + return nil, err + } + + // Parse the key + var pkey *bign.PrivateKey + if pkey, err = bign.ParseECPrivateKey(blockDecrypted); err != nil { + return nil, err + } + + return pkey, nil +} + +// ========== + +// 解析私钥 +func (this Bign) ParsePKCS8PrivateKeyFromPEM(key []byte) (*bign.PrivateKey, error) { + var err error + + // Parse PEM block + var block *pem.Block + if block, _ = pem.Decode(key); block == nil { + return nil, ErrKeyMustBePEMEncoded + } + + // Parse the key + var pkey *bign.PrivateKey + if pkey, err = bign.ParsePrivateKey(block.Bytes); err != nil { + return nil, err + } + + return pkey, nil +} + +// 解析 PKCS8 带密码的私钥 +func (this Bign) ParsePKCS8PrivateKeyFromPEMWithPassword(key []byte, password string) (*bign.PrivateKey, error) { + var err error + + // Parse PEM block + var block *pem.Block + if block, _ = pem.Decode(key); block == nil { + return nil, ErrKeyMustBePEMEncoded + } + + var blockDecrypted []byte + if blockDecrypted, err = pkcs8.DecryptPEMBlock(block, []byte(password)); err != nil { + return nil, err + } + + var pkey *bign.PrivateKey + if pkey, err = bign.ParsePrivateKey(blockDecrypted); err != nil { + return nil, err + } + + return pkey, nil +} + +// ========== + +// 解析公钥 +func (this Bign) ParsePublicKeyFromPEM(key []byte) (*bign.PublicKey, error) { + var err error + + // Parse PEM block + var block *pem.Block + if block, _ = pem.Decode(key); block == nil { + return nil, ErrKeyMustBePEMEncoded + } + + // Parse the key + var parsedKey any + if parsedKey, err = bign.ParsePublicKey(block.Bytes); err != nil { + if cert, err := x509.ParseCertificate(block.Bytes); err == nil { + parsedKey = cert.PublicKey + } else { + return nil, err + } + } + + var pkey *bign.PublicKey + var ok bool + + if pkey, ok = parsedKey.(*bign.PublicKey); !ok { + return nil, ErrNotECPublicKey + } + + return pkey, nil +} diff --git a/cryptobin/bign/sign.go b/cryptobin/bign/sign.go new file mode 100644 index 0000000..f3ddecd --- /dev/null +++ b/cryptobin/bign/sign.go @@ -0,0 +1,119 @@ +package bign + +import ( + "errors" + "crypto/rand" + + "github.com/deatil/go-cryptobin/pubkey/bign" +) + +// 私钥签名 +func (this Bign) Sign() Bign { + switch this.encoding { + case EncodingASN1: + return this.SignASN1() + case EncodingBytes: + return this.SignBytes() + } + + return this.SignASN1() +} + +// 公钥验证 +// 使用原始数据[data]对比签名后数据 +func (this Bign) Verify(data []byte) Bign { + switch this.encoding { + case EncodingASN1: + return this.VerifyASN1(data) + case EncodingBytes: + return this.VerifyBytes(data) + } + + return this.VerifyASN1(data) +} + +// =============== + +// 私钥签名 ASN1 +func (this Bign) SignASN1() Bign { + if this.privateKey == nil { + err := errors.New("privateKey empty.") + return this.AppendError(err) + } + + if this.signHash == nil { + err := errors.New("Hash func not set.") + return this.AppendError(err) + } + + sig, err := bign.Sign(rand.Reader, this.privateKey, this.signHash, this.data, this.adata) + if err != nil { + return this.AppendError(err) + } + + this.parsedData = sig + + return this.AppendError(err) +} + + +// 公钥验证 ASN1 +// 使用原始数据[data]对比签名后数据 +func (this Bign) VerifyASN1(data []byte) Bign { + if this.publicKey == nil { + err := errors.New("publicKey empty.") + return this.AppendError(err) + } + + if this.signHash == nil { + err := errors.New("Hash func not set.") + return this.AppendError(err) + } + + this.verify = bign.Verify(this.publicKey, this.signHash, data, this.adata, this.data) + + return this +} + + +// =============== + +// 私钥签名 Bytes +func (this Bign) SignBytes() Bign { + if this.privateKey == nil { + err := errors.New("privateKey empty.") + return this.AppendError(err) + } + + if this.signHash == nil { + err := errors.New("Hash func not set.") + return this.AppendError(err) + } + + sig, err := bign.SignBytes(rand.Reader, this.privateKey, this.signHash, this.data, this.adata) + if err != nil { + return this.AppendError(err) + } + + this.parsedData = sig + + return this.AppendError(err) +} + +// 公钥验证 Bytes +// 使用原始数据[data]对比签名后数据 +func (this Bign) VerifyBytes(data []byte) Bign { + if this.publicKey == nil { + err := errors.New("publicKey empty.") + return this.AppendError(err) + } + + if this.signHash == nil { + err := errors.New("Hash func not set.") + return this.AppendError(err) + } + + this.verify = bign.VerifyBytes(this.publicKey, this.signHash, data, this.adata, this.data) + + return this +} diff --git a/cryptobin/bign/sign_test.go b/cryptobin/bign/sign_test.go new file mode 100644 index 0000000..eaedfb5 --- /dev/null +++ b/cryptobin/bign/sign_test.go @@ -0,0 +1,189 @@ +package bign + +import ( + "testing" + + cryptobin_test "github.com/deatil/go-cryptobin/tool/test" +) + +var ( + prikey = ` +-----BEGIN PRIVATE KEY----- +MIGMAgEAMBgGCipwAAIAImUtAgEGCipwAAIAImUtAwEEbTBrAgEBBCDExu0qBLnd +FDEfEXc2Nft72QD2J2HYRr3EU4x0QM1BBqFEA0IABG5NUyNKNtnu+/7/7ODqSOtG +7oCtUEuRqVgvnireGA69uO5KS/RgAsf9ERVDZJHxKtwOYIXS2+/seXz/0sX+NPU= +-----END PRIVATE KEY----- + ` + + pubkey = ` +-----BEGIN PUBLIC KEY----- +MF4wGAYKKnAAAgAiZS0CAQYKKnAAAgAiZS0DAQNCAARuTVMjSjbZ7vv+/+zg6kjr +Ru6ArVBLkalYL54q3hgOvbjuSkv0YALH/REVQ2SR8SrcDmCF0tvv7Hl8/9LF/jT1 +-----END PUBLIC KEY----- + ` + + pubkey2 = ` +-----BEGIN PUBLIC KEY----- +MFEwEwYKKnAAAgAiZS0CAQYFK4EEACEDOgAEzcoYnYchmsKJIu3IIFF8X6L91Vv3 +M2Nie29mugemzh6T00lM1bDeD1PqBs8weCpFFv20s62c3CQ= +-----END PUBLIC KEY----- + ` +) + +func Test_SignASN1_And_VerifyASN1(t *testing.T) { + assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) + assertError := cryptobin_test.AssertErrorT(t) + assertBool := cryptobin_test.AssertBoolT(t) + + data := "test-pass" + adata := []byte{ + 0x00, 0x0b, 0x00, 0x00, + 0x06, 0x09, 0x2A, 0x70, 0x00, 0x02, 0x00, 0x22, 0x65, 0x1F, 0x51, + } + + { + objSign := NewBign(). + FromString(data). + FromPrivateKey([]byte(prikey)). + WithAdata(adata). + SignASN1() + + assertError(objSign.Error(), "SignASN1") + assertNotEmpty(objSign.ToBase64String(), "SignASN1") + } + + { + sig := "MDMCD2xLWwgWCM9JjiU3+dZxDAIgGBtQI9XH1aGuOFJztX+ImtyK3zoXbHTt/vBoNMr2ug0=" + objVerify := NewBign(). + FromBase64String(sig). + FromPublicKey([]byte(pubkey)). + WithAdata(adata). + VerifyASN1([]byte(data)) + + assertError(objVerify.Error(), "VerifyASN1") + assertBool(objVerify.ToVerify(), "VerifyASN1") + } +} + +func Test_Sign(t *testing.T) { + assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) + assertBool := cryptobin_test.AssertBoolT(t) + assertError := cryptobin_test.AssertErrorT(t) + + data := "test-pass" + adata := []byte{ + 0x00, 0x0b, 0x00, 0x00, + 0x06, 0x09, 0x2A, 0x70, 0x00, 0x02, 0x00, 0x22, 0x65, 0x1F, 0x51, + } + + // 签名 + objSign := New(). + FromString(data). + FromPrivateKey([]byte(prikey)). + WithAdata(adata). + Sign() + signed := objSign.ToBase64String() + + assertError(objSign.Error(), "Sign-Sign") + assertNotEmpty(signed, "Sign-Sign") + + // 验证 + objVerify := New(). + FromBase64String(signed). + FromPublicKey([]byte(pubkey)). + WithAdata(adata). + Verify([]byte(data)) + + assertError(objVerify.Error(), "Sign-Verify") + assertBool(objVerify.ToVerify(), "Sign-Verify") +} + +func Test_SignASN1(t *testing.T) { + assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) + assertBool := cryptobin_test.AssertBoolT(t) + assertError := cryptobin_test.AssertErrorT(t) + + data := "test-pass" + adata := []byte{ + 0x00, 0x0b, 0x00, 0x00, + 0x06, 0x09, 0x2A, 0x70, 0x00, 0x02, 0x00, 0x22, 0x65, 0x1F, 0x51, + } + + // 签名 + objSign := New(). + FromString(data). + FromPrivateKey([]byte(prikey)). + WithAdata(adata). + SignASN1() + signed := objSign.ToBase64String() + + assertError(objSign.Error(), "SignASN12-Sign") + assertNotEmpty(signed, "SignASN12-Sign") + + // 验证 + objVerify := New(). + FromBase64String(signed). + FromPublicKey([]byte(pubkey)). + WithAdata(adata). + VerifyASN1([]byte(data)) + + assertError(objVerify.Error(), "SignASN12-Verify") + assertBool(objVerify.ToVerify(), "SignASN12-Verify") +} + +func Test_SignBytes(t *testing.T) { + assertNotEmpty := cryptobin_test.AssertNotEmptyT(t) + assertBool := cryptobin_test.AssertBoolT(t) + assertError := cryptobin_test.AssertErrorT(t) + + data := "test-pass" + adata := []byte{ + 0x00, 0x0b, 0x00, 0x00, + 0x06, 0x09, 0x2A, 0x70, 0x00, 0x02, 0x00, 0x22, 0x65, 0x1F, 0x51, + } + + // 签名 + objSign := New(). + FromString(data). + FromPrivateKey([]byte(prikey)). + WithAdata(adata). + SignBytes() + signed := objSign.ToBase64String() + + assertError(objSign.Error(), "SignBytes-Sign") + assertNotEmpty(signed, "SignBytes-Sign") + + // 验证 + objVerify := New(). + FromBase64String(signed). + FromPublicKey([]byte(pubkey)). + WithAdata(adata). + VerifyBytes([]byte(data)) + + assertError(objVerify.Error(), "SignBytes-Verify") + assertBool(objVerify.ToVerify(), "SignBytes-Verify") +} + +func Test_CheckKeyPair(t *testing.T) { + assertBool := cryptobin_test.AssertBoolT(t) + assertError := cryptobin_test.AssertErrorT(t) + + { + obj := New(). + FromPrivateKey([]byte(prikey)). + FromPublicKey([]byte(pubkey)) + + assertError(obj.Error(), "CheckKeyPair") + assertBool(obj.CheckKeyPair(), "CheckKeyPair") + } + + { + obj := New(). + FromPrivateKey([]byte(prikey)). + FromPublicKey([]byte(pubkey2)) + + assertError(obj.Error(), "CheckKeyPair 2") + assertBool(!obj.CheckKeyPair(), "CheckKeyPair 2") + } + +} diff --git a/cryptobin/bign/to.go b/cryptobin/bign/to.go new file mode 100644 index 0000000..742889a --- /dev/null +++ b/cryptobin/bign/to.go @@ -0,0 +1,53 @@ +package bign + +import ( + "github.com/deatil/go-cryptobin/tool" +) + +// 私钥/公钥 +func (this Bign) ToKeyBytes() []byte { + return this.keyData +} + +// 私钥/公钥 +func (this Bign) ToKeyString() string { + return string(this.keyData) +} + +// ========== + +// 输出字节 +func (this Bign) ToBytes() []byte { + return this.parsedData +} + +// 输出字符 +func (this Bign) ToString() string { + return string(this.parsedData) +} + +// 输出Base64 +func (this Bign) ToBase64String() string { + return tool.Base64Encode(this.parsedData) +} + +// 输出Hex +func (this Bign) ToHexString() string { + return tool.HexEncode(this.parsedData) +} + +// ========== + +// 验证结果 +func (this Bign) ToVerify() bool { + return this.verify +} + +// 验证结果,返回 int 类型 +func (this Bign) ToVerifyInt() int { + if this.verify { + return 1 + } + + return 0 +} diff --git a/cryptobin/bign/with.go b/cryptobin/bign/with.go new file mode 100644 index 0000000..8430e7e --- /dev/null +++ b/cryptobin/bign/with.go @@ -0,0 +1,116 @@ +package bign + +import ( + "crypto/elliptic" + + "github.com/deatil/go-cryptobin/tool" + "github.com/deatil/go-cryptobin/pubkey/bign" + ecbign "github.com/deatil/go-cryptobin/elliptic/bign" +) + +// 设置 PrivateKey +func (this Bign) WithPrivateKey(data *bign.PrivateKey) Bign { + this.privateKey = data + + return this +} + +// 设置 PublicKey +func (this Bign) WithPublicKey(data *bign.PublicKey) Bign { + this.publicKey = data + + return this +} + +// 设置曲线类型 +func (this Bign) WithCurve(curve elliptic.Curve) Bign { + this.curve = curve + + return this +} + +// 设置曲线类型 +// 可选 [Bign256v1 | Bign384v1 | Bign512v1] +func (this Bign) SetCurve(curve string) Bign { + switch curve { + case "Bign256v1": + this.curve = ecbign.P256v1() + case "Bign384v1": + this.curve = ecbign.P384v1() + case "Bign512v1": + this.curve = ecbign.P512v1() + } + + return this +} + +// 设置 hash 类型 +func (this Bign) WithSignHash(hash HashFunc) Bign { + this.signHash = hash + + return this +} + +// 设置 hash 类型 +func (this Bign) SetSignHash(hash string) Bign { + h, err := tool.GetHash(hash) + if err != nil { + return this.AppendError(err) + } + + this.signHash = h + + return this +} + +// 设置 data +func (this Bign) WithData(data []byte) Bign { + this.data = data + + return this +} + +// 设置 adata +func (this Bign) WithAdata(adata []byte) Bign { + this.adata = adata + + return this +} + +// 设置 parsedData +func (this Bign) WithParsedData(data []byte) Bign { + this.parsedData = data + + return this +} + +// 设置编码方式 +func (this Bign) WithEncoding(encoding EncodingType) Bign { + this.encoding = encoding + + return this +} + +// 设置 ASN1 编码方式 +func (this Bign) WithEncodingASN1() Bign { + return this.WithEncoding(EncodingASN1) +} + +// 设置明文编码方式 +func (this Bign) WithEncodingBytes() Bign { + return this.WithEncoding(EncodingBytes) +} + +// 设置验证结果 +func (this Bign) WithVerify(data bool) Bign { + this.verify = data + + return this +} + +// 设置错误 +func (this Bign) WithErrors(errs []error) Bign { + this.Errors = errs + + return this +} diff --git a/docs/README.md b/docs/README.md index b6f2897..fd8149e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -13,6 +13,7 @@ * elgamal 使用文档: [elgamal.md](elgamal.md) * ed448 使用文档: [ed448.md](ed448.md) * gost 使用文档: [gost.md](gost.md) +* bign 使用文档: [bign.md](bign.md) * dh 使用文档: [dh.md](dh.md) * ca 使用文档: [ca.md](ca.md) * pkcs7 使用文档: [pkcs7.md](pkcs7.md) diff --git a/docs/bign.md b/docs/bign.md new file mode 100644 index 0000000..4caf5fb --- /dev/null +++ b/docs/bign.md @@ -0,0 +1,131 @@ +### Bign 使用文档 + +#### 包引入 +~~~go +import ( + "github.com/deatil/go-cryptobin/cryptobin/bign" +) +~~~ + +#### 数据输入方式 / input funcs +~~~go +FromBytes(data []byte) +FromString(data string) +FromBase64String(data string) +FromHexString(data string) +~~~ + +#### 数据输出方式 / output funcs +~~~go +ToBytes() +ToString() +ToBase64String() +ToHexString() +~~~ + +#### 获取 error / get error +~~~go +Error() +~~~ + +#### 生成证书 +~~~go +func main() { + // 私钥密码 + // privatekey password + var psssword string = "" + + // 生成证书 + // 可选 [Bign256v1 | Bign384v1 | Bign512v1] + gen := bign.GenerateKey("Bign256v1") + + // 生成私钥 PEM 证书 + privateKeyString := gen. + CreatePrivateKey(). + // CreatePrivateKeyWithPassword(psssword, "AES256CBC"). + // CreatePKCS1PrivateKey() + // CreatePKCS1PrivateKeyWithPassword(password string, opts ...string) + // CreatePKCS8PrivateKey(). + // CreatePKCS8PrivateKeyWithPassword(psssword, "AES256CBC", "SHA256"). + ToKeyString() + + // 生成公钥 PEM 证书 + publicKeyString := gen. + CreatePublicKey(). + ToKeyString() +} +~~~ + +#### 签名验证 + +签名验证支持以下方式 +~~~ +默认方法: +Sign() / Verify(data []byte) + +ASN1编码,为默认方法别名: +SignASN1() / VerifyASN1(data []byte) + +明文字节拼接: +SignBytes() / VerifyBytes(data []byte) +~~~ + +示例 +~~~go +func main() { + // 私钥密码 + // privatekey password + var psssword string = "" + + // 私钥签名 + var pri []byte = []byte("...") + var base64signedString string = bign. + FromString("test-pass"). + FromPrivateKey(pri). + // FromPrivateKeyWithPassword(pri, psssword). + // FromPKCS1PrivateKey(pri). + // FromPKCS1PrivateKeyWithPassword(pri, psssword). + // FromPKCS8PrivateKey(pri). + // FromPKCS8PrivateKeyWithPassword(pri, psssword). + // WithEncodingASN1(). + // WithEncodingBytes(). + WithAdata(adata). // 设置 adata 参数 + Sign(). + ToBase64String() + + // 公钥验证 + var pub []byte = []byte("...") + var base64signedString string = "..." + var verify bool = bign. + FromBase64String(base64signedString). + FromPublicKey(pub). + // WithEncodingASN1(). + // WithEncodingBytes(). + WithAdata(adata). // 设置 adata 参数 + Verify([]byte("test-pass")). + ToVerify() +} +~~~ + + +#### 检测私钥公钥是否匹配 +~~~go +func main() { + // 私钥密码 + // privatekey password + var psssword string = "" + + var prikeyPem []byte = []byte("...") + var pubkeyPem []byte = []byte("...") + + var res bool = bign.New(). + FromPrivateKey(pri). + // FromPrivateKeyWithPassword(pri, psssword). + // FromPKCS1PrivateKey(pri). + // FromPKCS1PrivateKeyWithPassword(pri, psssword). + // FromPKCS8PrivateKey(pri). + // FromPKCS8PrivateKeyWithPassword(pri, psssword). + FromPublicKey(pubkey). + CheckKeyPair() +} +~~~ diff --git a/docs/ecdsa.md b/docs/ecdsa.md index 6f3f14f..a4e05d1 100644 --- a/docs/ecdsa.md +++ b/docs/ecdsa.md @@ -66,7 +66,7 @@ Sign() / Verify(data []byte) ASN1编码,为默认方法别名: SignASN1() / VerifyASN1(data []byte) -字节拼接: +明文字节拼接: SignBytes() / VerifyBytes(data []byte) ~~~ diff --git a/docs/ecgdsa.md b/docs/ecgdsa.md index 05b588d..75a60a7 100644 --- a/docs/ecgdsa.md +++ b/docs/ecgdsa.md @@ -66,7 +66,7 @@ Sign() / Verify(data []byte) ASN1编码,为默认方法别名: SignASN1() / VerifyASN1(data []byte) -字节拼接: +明文字节拼接: SignBytes() / VerifyBytes(data []byte) ~~~ diff --git a/pubkey/bign/bign.go b/pubkey/bign/bign.go index d2fd5f7..bc4c677 100644 --- a/pubkey/bign/bign.go +++ b/pubkey/bign/bign.go @@ -69,7 +69,7 @@ func (opts *SignerOpts) GetAdata() []byte { return opts.Adata } -// ec-gdsa PublicKey +// bign PublicKey type PublicKey struct { elliptic.Curve @@ -98,7 +98,7 @@ func (pub *PublicKey) Verify(msg, sign []byte, opts crypto.SignerOpts) (bool, er return Verify(pub, opt.GetHash(), msg, opt.GetAdata(), sign), nil } -// ec-gdsa PrivateKey +// bign PrivateKey type PrivateKey struct { PublicKey diff --git a/pubkey/bign/utils.go b/pubkey/bign/utils.go index 27353e6..533a605 100644 --- a/pubkey/bign/utils.go +++ b/pubkey/bign/utils.go @@ -106,12 +106,12 @@ const MAX_DIGEST_SIZE = 64 func determiniticNonce( k, q *big.Int, - q_bit_len int, + qBitLen int, x *big.Int, adata []byte, h []byte, ) error { - qlen := (q_bit_len + 7) / 8 + qlen := (qBitLen + 7) / 8 l := qlen / 2 hlen := len(h) @@ -200,8 +200,8 @@ func determiniticNonce( r_bar_len = qlen copy(r_bar[:], r[:r_bar_len]) - if (q_bit_len % 8) != 0 { - r_bar[r_bar_len - 1] &= byte((0x1 << (q_bit_len % 8)) - 1) + if (qBitLen % 8) != 0 { + r_bar[r_bar_len - 1] &= byte((0x1 << (qBitLen % 8)) - 1) } } else { if (n * BELT_BLOCK_LEN) > 0xffff {