diff --git a/cryptobin/ca/alias.go b/cryptobin/ca/alias.go index eab3d55..df12c53 100644 --- a/cryptobin/ca/alias.go +++ b/cryptobin/ca/alias.go @@ -6,9 +6,8 @@ import ( "github.com/deatil/go-cryptobin/x509" ) -// pkix type ( - // Subject 数据 + // Subject data PkixName = pkix.Name // Extension @@ -36,15 +35,14 @@ type ( PkixAttributeTypeAndValueSET = pkix.AttributeTypeAndValueSET ) -// x905 type ( - // 证书 + // Certificate Certificate = x509.Certificate - // 证书请求 + // CertificateRequest CertificateRequest = x509.CertificateRequest - // 配置别名 + // VerifyOptions VerifyOptions = x509.VerifyOptions // KeyUsage diff --git a/cryptobin/ca/ca.go b/cryptobin/ca/ca.go index 7ba2f39..7c916ef 100644 --- a/cryptobin/ca/ca.go +++ b/cryptobin/ca/ca.go @@ -29,6 +29,8 @@ func (typ PublicKeyType) String() string { return "SM2" case KeyTypeGost: return "Gost" + case KeyTypeElGamal: + return "ElGamal" default: return "unknown KeyType value " + strconv.Itoa(int(typ)) } @@ -42,6 +44,7 @@ const ( KeyTypeEdDSA KeyTypeSM2 KeyTypeGost + KeyTypeElGamal ) // Options @@ -49,17 +52,20 @@ type Options struct { // public key type PublicKeyType PublicKeyType - // DSA ParameterSizes + // generates DSA ParameterSizes ParameterSizes dsa.ParameterSizes - // ecc curve + // generates ECC curve Curve elliptic.Curve - // gost curve + // generates Gost curve GostCurve *gost.Curve // generates RSA private key bit size Bits int + + // generates ElGamal private key bit size and probability + Bitsize, Probability int } /** @@ -102,6 +108,8 @@ func NewCA() CA { Curve: elliptic.P256(), GostCurve: gost.CurveDefault(), Bits: 2048, + Bitsize: 256, + Probability: 64, }, Errors: make([]error, 0), } diff --git a/cryptobin/ca/ca_test.go b/cryptobin/ca/ca_test.go index 5328338..e2d6541 100644 --- a/cryptobin/ca/ca_test.go +++ b/cryptobin/ca/ca_test.go @@ -481,6 +481,44 @@ func Test_GenerateKey(t *testing.T) { assertEqual(pubkey22, obj.GetPublicKey(), "Test_GenerateKey-FromPublicKey") }) + t.Run("GenerateElGamalKey", func(t *testing.T) { + obj := New(). + SetPublicKeyType("ElGamal"). + WithBitsize(256). + WithProbability(64). + GenerateKey() + + prikey := obj.CreatePrivateKey().ToKeyString() + pubkey := obj.CreatePublicKey().ToKeyString() + + assertError(obj.Error(), "Test_GenerateKey") + assertNotEmpty(prikey, "Test_GenerateKey-prikey") + assertNotEmpty(pubkey, "Test_GenerateKey-pubkey") + + pass := []byte("12345678") + prikey2 := obj.CreatePrivateKeyWithPassword(pass).ToKeyString() + + assertNotEmpty(prikey2, "Test_GenerateKey-prikey2") + + prikey22 := New(). + FromPrivateKey([]byte(prikey)) + + assertEqual(prikey22.GetPrivateKey(), obj.GetPrivateKey(), "Test_GenerateKey-FromPrivateKey") + assertEqual(prikey22.GetPrivateKeyType().String(), "ElGamal", "Test_GenerateKey-GetPrivateKeyType") + + prikey223 := New(). + FromPrivateKeyWithPassword([]byte(prikey2), pass) + + assertEqual(prikey223.GetPrivateKey(), obj.GetPrivateKey(), "Test_GenerateKey-FromPrivateKeyWithPassword") + assertEqual(prikey223.GetPrivateKeyType().String(), "ElGamal", "Test_GenerateKey-GetPrivateKeyType") + + pubkey22 := New(). + FromPublicKey([]byte(pubkey)) + + assertEqual(pubkey22.GetPublicKey(), obj.GetPublicKey(), "Test_GenerateKey-FromPublicKey") + assertEqual(pubkey22.GetPublicKeyType().String(), "ElGamal", "Test_GenerateKey-GetPublicKeyType") + }) + t.Run("GenerateRSAKey 2", func(t *testing.T) { obj := New(). SetGenerateType("RSA"). @@ -592,6 +630,18 @@ func Test_GenerateKey2(t *testing.T) { assertNotEmpty(pubkey, "Test_GenerateKey2-pubkey") }) + t.Run("GenerateElGamalKey", func(t *testing.T) { + obj := New(). + GenerateElGamalKey(256, 64) + + prikey := obj.CreatePrivateKey().ToKeyString() + pubkey := obj.CreatePublicKey().ToKeyString() + + assertError(obj.Error(), "Test_GenerateKey2") + assertNotEmpty(prikey, "Test_GenerateKey2-prikey") + assertNotEmpty(pubkey, "Test_GenerateKey2-pubkey") + }) + } var prikey = ` @@ -759,6 +809,8 @@ func Test_Get(t *testing.T) { Curve: elliptic.P256(), GostCurve: gost.CurveIdGostR34102001CryptoProAParamSet(), Bits: 2048, + Bitsize: 256, + Probability: 64, } newCA2 := CA{ @@ -785,6 +837,8 @@ func Test_Get(t *testing.T) { assertEqual(newCA2.GetCurve(), elliptic.P256(), "Test_Get-GetCurve") assertEqual(newCA2.GetGostCurve(), gost.CurveIdGostR34102001CryptoProAParamSet(), "Test_Get-GetGostCurve") assertEqual(newCA2.GetBits(), 2048, "Test_Get-GetBits") + assertEqual(newCA2.GetBitsize(), 256, "Test_Get-GetBitsize") + assertEqual(newCA2.GetProbability(), 64, "Test_Get-GetProbability") assertEqual(newCA2.GetKeyData(), []byte("test-keyData"), "Test_Get-GetKeyData") assertEqual(newCA2.GetErrors(), []error{testerr}, "Test_Get-GetErrors") @@ -864,6 +918,12 @@ func Test_With(t *testing.T) { tmp = newCA.WithBits(2048) assertEqual(tmp.options.Bits, 2048, "Test_Get-WithBits") + tmp = newCA.WithBitsize(2038) + assertEqual(tmp.options.Bitsize, 2038, "Test_Get-WithBitsize") + + tmp = newCA.WithProbability(2028) + assertEqual(tmp.options.Probability, 2028, "Test_Get-WithProbability") + tmp = newCA.WithKeyData([]byte("test-keyData")) assertEqual(tmp.keyData, []byte("test-keyData"), "Test_Get-WithKeyData") diff --git a/cryptobin/ca/create.go b/cryptobin/ca/create.go index c1c7535..c80b852 100644 --- a/cryptobin/ca/create.go +++ b/cryptobin/ca/create.go @@ -16,6 +16,7 @@ import ( "github.com/deatil/go-cryptobin/pkcs12" "github.com/deatil/go-cryptobin/gm/sm2" "github.com/deatil/go-cryptobin/pubkey/gost" + "github.com/deatil/go-cryptobin/pubkey/elgamal" cryptobin_x509 "github.com/deatil/go-cryptobin/x509" pubkey_dsa "github.com/deatil/go-cryptobin/pubkey/dsa" ) @@ -136,6 +137,8 @@ func (this CA) CreatePrivateKey() CA { privateKeyBytes, err = sm2.MarshalPrivateKey(privateKey) case *gost.PrivateKey: privateKeyBytes, err = gost.MarshalPrivateKey(privateKey) + case *elgamal.PrivateKey: + privateKeyBytes, err = elgamal.MarshalPKCS8PrivateKey(privateKey) default: err = fmt.Errorf("unsupported private key type: %T", privateKey) } @@ -182,6 +185,8 @@ func (this CA) CreatePrivateKeyWithPassword(password []byte, opts ...any) CA { privateKeyBytes, err = sm2.MarshalPrivateKey(prikey) case *gost.PrivateKey: privateKeyBytes, err = gost.MarshalPrivateKey(prikey) + case *elgamal.PrivateKey: + privateKeyBytes, err = elgamal.MarshalPKCS8PrivateKey(prikey) default: err = errors.New("privateKey error.") } @@ -230,6 +235,8 @@ func (this CA) CreatePublicKey() CA { publicKeyBytes, err = sm2.MarshalPublicKey(pubkey) case *gost.PublicKey: publicKeyBytes, err = gost.MarshalPublicKey(pubkey) + case *elgamal.PublicKey: + publicKeyBytes, err = elgamal.MarshalPKCS8PublicKey(pubkey) default: err = errors.New("privateKey error.") } diff --git a/cryptobin/ca/from.go b/cryptobin/ca/from.go index b99aa6f..db9c1ec 100644 --- a/cryptobin/ca/from.go +++ b/cryptobin/ca/from.go @@ -12,6 +12,7 @@ import ( "github.com/deatil/go-cryptobin/pkcs12" "github.com/deatil/go-cryptobin/gm/sm2" "github.com/deatil/go-cryptobin/pubkey/gost" + "github.com/deatil/go-cryptobin/pubkey/elgamal" ) // Generate Key with Reader @@ -62,6 +63,14 @@ func (this CA) GenerateKeyWithSeed(reader io.Reader) CA { return this.AppendError(err) } + this.privateKey = privateKey + this.publicKey = &privateKey.PublicKey + case KeyTypeElGamal: + privateKey, err := elgamal.GenerateKey(reader, this.options.Bitsize, this.options.Probability) + if err != nil { + return this.AppendError(err) + } + this.privateKey = privateKey this.publicKey = &privateKey.PublicKey } @@ -287,3 +296,16 @@ func (this CA) GenerateGostKey(curve string) CA { func GenerateGostKey(curve string) CA { return defaultCA.GenerateGostKey(curve) } + +// Generate ElGamal key +func (this CA) GenerateElGamalKey(bitsize, probability int) CA { + return this.SetPublicKeyType("ElGamal"). + WithBitsize(bitsize). + WithProbability(probability). + GenerateKey() +} + +// Generate ElGamal Key +func GenerateElGamalKey(bitsize, probability int) CA { + return defaultCA.GenerateElGamalKey(bitsize, probability) +} diff --git a/cryptobin/ca/get.go b/cryptobin/ca/get.go index 3cae5b4..9a2e3b4 100644 --- a/cryptobin/ca/get.go +++ b/cryptobin/ca/get.go @@ -11,6 +11,7 @@ import ( "github.com/deatil/go-cryptobin/x509" "github.com/deatil/go-cryptobin/gm/sm2" "github.com/deatil/go-cryptobin/pubkey/gost" + "github.com/deatil/go-cryptobin/pubkey/elgamal" ) // 获取 cert @@ -43,6 +44,8 @@ func (this CA) GetPrivateKeyType() PublicKeyType { return KeyTypeSM2 case *gost.PrivateKey: return KeyTypeGost + case *elgamal.PrivateKey: + return KeyTypeElGamal } return KeyTypeUnknown @@ -68,6 +71,8 @@ func (this CA) GetPublicKeyType() PublicKeyType { return KeyTypeSM2 case *gost.PublicKey: return KeyTypeGost + case *elgamal.PublicKey: + return KeyTypeElGamal } return KeyTypeUnknown @@ -98,6 +103,16 @@ func (this CA) GetBits() int { return this.options.Bits } +// get Options Bitsize +func (this CA) GetBitsize() int { + return this.options.Bitsize +} + +// get Options Probability +func (this CA) GetProbability() int { + return this.options.Probability +} + // 获取 keyData func (this CA) GetKeyData() []byte { return this.keyData diff --git a/cryptobin/ca/make.go b/cryptobin/ca/make.go index b1b6e7e..7e9d4bc 100644 --- a/cryptobin/ca/make.go +++ b/cryptobin/ca/make.go @@ -96,8 +96,8 @@ func (this CA) MakeCSR( CommonName: commonName, Organization: organization, - // Country: country, // OrganizationalUnit: organizationalUnit, + // Country: country, // Locality: locality, // Province: province, // StreetAddress: streetAddress, @@ -132,23 +132,29 @@ func getSignatureAlgorithm(name string) x509.SignatureAlgorithm { data := map[string]x509.SignatureAlgorithm { "MD2WithRSA": x509.MD2WithRSA, "MD5WithRSA": x509.MD5WithRSA, - // "MD2WithRSA": x509.MD2WithRSA, // Unsupported. "SHA1WithRSA": x509.SHA1WithRSA, "SHA256WithRSA": x509.SHA256WithRSA, "SHA384WithRSA": x509.SHA384WithRSA, "SHA512WithRSA": x509.SHA512WithRSA, - // "DSAWithSHA1": x509.DSAWithSHA1, // Unsupported. - // "DSAWithSHA256": x509.DSAWithSHA256, // Unsupported. + "SHA256WithRSAPSS": x509.SHA256WithRSAPSS, + "SHA384WithRSAPSS": x509.SHA384WithRSAPSS, + "SHA512WithRSAPSS": x509.SHA512WithRSAPSS, + "PureEd25519": x509.PureEd25519, + "DSAWithSHA1": x509.DSAWithSHA1, + "DSAWithSHA256": x509.DSAWithSHA256, "ECDSAWithSHA1": x509.ECDSAWithSHA1, "ECDSAWithSHA256": x509.ECDSAWithSHA256, "ECDSAWithSHA384": x509.ECDSAWithSHA384, "ECDSAWithSHA512": x509.ECDSAWithSHA512, - "SHA256WithRSAPSS": x509.SHA256WithRSAPSS, - "SHA384WithRSAPSS": x509.SHA384WithRSAPSS, - "SHA512WithRSAPSS": x509.SHA512WithRSAPSS, "SM2WithSM3": x509.SM2WithSM3, "SM2WithSHA1": x509.SM2WithSHA1, "SM2WithSHA256": x509.SM2WithSHA256, + "SM3WithRSA": x509.SM3WithRSA, + "GOST3410WithGOST34112001": x509.GOST3410WithGOST34112001, + "GOST3410WithGOST34112012256": x509.GOST3410WithGOST34112012256, + "GOST3410WithGOST34112012512": x509.GOST3410WithGOST34112012512, + "ElGamalWithSHA1": x509.ElGamalWithSHA1, + "ElGamalWithRIPEMD160": x509.ElGamalWithRIPEMD160, } if alg, ok := data[name]; ok { diff --git a/cryptobin/ca/parse.go b/cryptobin/ca/parse.go index 85fe196..3e4bae5 100644 --- a/cryptobin/ca/parse.go +++ b/cryptobin/ca/parse.go @@ -11,6 +11,7 @@ import ( "github.com/deatil/go-cryptobin/pkcs8" "github.com/deatil/go-cryptobin/gm/sm2" "github.com/deatil/go-cryptobin/pubkey/gost" + "github.com/deatil/go-cryptobin/pubkey/elgamal" cryptobin_x509 "github.com/deatil/go-cryptobin/x509" pubkey_dsa "github.com/deatil/go-cryptobin/pubkey/dsa" ) @@ -23,15 +24,17 @@ var ( ) var ( - oidPublicKeySM2 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 301} oidPublicKeyRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1} oidPublicKeyDSA = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 1} oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1} oidPublicKeyEd25519 = asn1.ObjectIdentifier{1, 3, 101, 112} + oidPublicKeySM2 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 301} + + oidGOSTPublicKey = asn1.ObjectIdentifier{1, 2, 643, 2, 2, 19} + oidGost2012PublicKey256 = asn1.ObjectIdentifier{1, 2, 643, 7, 1, 1, 1, 1} + oidGost2012PublicKey512 = asn1.ObjectIdentifier{1, 2, 643, 7, 1, 1, 1, 2} - oidGOSTPublicKey = asn1.ObjectIdentifier{1, 2, 643, 2, 2, 19} - oidGost2012PublicKey256 = asn1.ObjectIdentifier{1, 2, 643, 7, 1, 1, 1, 1} - oidGost2012PublicKey512 = asn1.ObjectIdentifier{1, 2, 643, 7, 1, 1, 1, 2} + oidPublicKeyElGamal = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 3029, 1, 2, 1} ) type pkcs8Info struct { @@ -89,6 +92,8 @@ func (this CA) ParsePKCS8PrivateKeyFromPEM(key []byte) (crypto.PrivateKey, error privKey.Algo.Algorithm.Equal(oidGost2012PublicKey256), privKey.Algo.Algorithm.Equal(oidGost2012PublicKey512): parsedKey, err = gost.ParsePrivateKey(block.Bytes) + case privKey.Algo.Algorithm.Equal(oidPublicKeyElGamal): + parsedKey, err = elgamal.ParsePKCS8PrivateKey(block.Bytes) default: return nil, ErrPrivateKeyError } @@ -148,6 +153,8 @@ func (this CA) ParsePKCS8PrivateKeyFromPEMWithPassword(key []byte, password []by privKey.Algo.Algorithm.Equal(oidGost2012PublicKey256), privKey.Algo.Algorithm.Equal(oidGost2012PublicKey512): parsedKey, err = gost.ParsePrivateKey(blockDecrypted) + case privKey.Algo.Algorithm.Equal(oidPublicKeyElGamal): + parsedKey, err = elgamal.ParsePKCS8PrivateKey(blockDecrypted) default: return nil, ErrPrivateKeyError } @@ -202,6 +209,8 @@ func (this CA) ParsePKCS8PublicKeyFromPEM(key []byte) (crypto.PublicKey, error) pubkey.Algo.Algorithm.Equal(oidGost2012PublicKey256), pubkey.Algo.Algorithm.Equal(oidGost2012PublicKey512): parsedKey, err = gost.ParsePublicKey(block.Bytes) + case pubkey.Algo.Algorithm.Equal(oidPublicKeyElGamal): + parsedKey, err = elgamal.ParsePKCS8PublicKey(block.Bytes) default: return nil, ErrPublicKeyError } diff --git a/cryptobin/ca/with.go b/cryptobin/ca/with.go index 3fbc8ea..951adc5 100644 --- a/cryptobin/ca/with.go +++ b/cryptobin/ca/with.go @@ -53,7 +53,7 @@ func (this CA) WithPublicKeyType(keyType PublicKeyType) CA { // set public key type // params: -// [ RSA | DSA | ECDSA | EdDSA | SM2 | Gost ] +// [ RSA | DSA | ECDSA | EdDSA | SM2 | Gost | ElGamal ] func (this CA) SetPublicKeyType(keyType string) CA { switch keyType { case "RSA": @@ -68,6 +68,8 @@ func (this CA) SetPublicKeyType(keyType string) CA { this.options.PublicKeyType = KeyTypeSM2 case "Gost": this.options.PublicKeyType = KeyTypeGost + case "ElGamal": + this.options.PublicKeyType = KeyTypeElGamal } return this @@ -75,7 +77,7 @@ func (this CA) SetPublicKeyType(keyType string) CA { // set Generate public key type // params: -// [ RSA | DSA | ECDSA | EdDSA | SM2 ] +// [ RSA | DSA | ECDSA | EdDSA | SM2 | Gost | ElGamal ] func (this CA) SetGenerateType(typ string) CA { return this.SetPublicKeyType(typ) } @@ -199,6 +201,20 @@ func (this CA) WithBits(bits int) CA { return this } +// ElGamal private key bit size +func (this CA) WithBitsize(bits int) CA { + this.options.Bitsize = bits + + return this +} + +// ElGamal private key probability size +func (this CA) WithProbability(probability int) CA { + this.options.Probability = probability + + return this +} + // 设置 keyData func (this CA) WithKeyData(data []byte) CA { this.keyData = data diff --git a/pubkey/elgamal/elgamal.go b/pubkey/elgamal/elgamal.go index d5e0446..77ee0f8 100644 --- a/pubkey/elgamal/elgamal.go +++ b/pubkey/elgamal/elgamal.go @@ -59,6 +59,7 @@ func (pub *PublicKey) Encrypt(random io.Reader, message []byte) ([]byte, error) // PrivateKey represents Elgamal private key. type PrivateKey struct { PublicKey + X *big.Int } diff --git a/x509/x509.go b/x509/x509.go index 7637bd8..5a44107 100644 --- a/x509/x509.go +++ b/x509/x509.go @@ -690,9 +690,9 @@ var ( oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1} oidPublicKeyEd25519 = asn1.ObjectIdentifier{1, 3, 101, 112} - oidGOSTPublicKey = asn1.ObjectIdentifier{1, 2, 643, 2, 2, 19} - oidGost2012PublicKey256 = asn1.ObjectIdentifier{1, 2, 643, 7, 1, 1, 1, 1} - oidGost2012PublicKey512 = asn1.ObjectIdentifier{1, 2, 643, 7, 1, 1, 1, 2} + oidGOSTPublicKey = asn1.ObjectIdentifier{1, 2, 643, 2, 2, 19} + oidGost2012PublicKey256 = asn1.ObjectIdentifier{1, 2, 643, 7, 1, 1, 1, 1} + oidGost2012PublicKey512 = asn1.ObjectIdentifier{1, 2, 643, 7, 1, 1, 1, 2} oidPublicKeyElGamal = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 3029, 1, 2, 1} )