@@ -3,13 +3,15 @@ package me.leon.ext.crypto
33import java.security.*
44import java.security.spec.PKCS8EncodedKeySpec
55import java.security.spec.X509EncodedKeySpec
6+ import me.leon.ext.hex2ByteArray
67import org.bouncycastle.asn1.gm.GMNamedCurves
78import org.bouncycastle.asn1.pkcs.PrivateKeyInfo
89import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo
910import org.bouncycastle.asn1.x9.ECNamedCurveTable
1011import org.bouncycastle.crypto.CipherParameters
1112import org.bouncycastle.crypto.engines.SM2Engine
1213import org.bouncycastle.crypto.params.*
14+ import org.bouncycastle.crypto.signers.SM2Signer
1315import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util
1416import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil
1517import org.bouncycastle.jcajce.spec.OpenSSHPrivateKeySpec
@@ -19,8 +21,10 @@ import org.bouncycastle.jce.interfaces.ECPublicKey
1921import org.bouncycastle.jce.provider.BouncyCastleProvider
2022import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec
2123import org.bouncycastle.util.BigIntegers
24+ import org.bouncycastle.util.Strings
2225
2326private val x9ECParameters = GMNamedCurves .getByName(" sm2p256v1" )
27+ private val USER_ID = Strings .toByteArray(" 1234567812345678" )
2428private val ecDomainParameters =
2529 ECDomainParameters (x9ECParameters.curve, x9ECParameters.g, x9ECParameters.n, x9ECParameters.h)
2630
@@ -58,6 +62,33 @@ fun ByteArray.toECPublicKeyParams(): AsymmetricKeyParameter {
5862 return generatePublicKeyParameter(public)
5963}
6064
65+ fun ByteArray.sm2Sign (privateKeyHex : String , userId : ByteArray = USER_ID ): ByteArray {
66+ val sm2Signer = SM2Signer ()
67+ val param = privateKeyHex.hex2ByteArray().toECPrivateKeyParams()
68+
69+ sm2Signer.init (
70+ true ,
71+ ParametersWithID (ParametersWithRandom (param, SecureRandom .getInstance(" SHA1PRNG" )), userId),
72+ )
73+ sm2Signer.update(this , 0 , this .size)
74+ return sm2Signer.generateSignature()
75+ }
76+
77+ fun ByteArray.sm2Verify (publicKey : String , signedHex : String ) =
78+ sm2Verify(publicKey, signedHex.hex2ByteArray())
79+
80+ fun ByteArray.sm2Verify (
81+ publicKey : String ,
82+ signed : ByteArray ,
83+ userId : ByteArray = USER_ID ,
84+ ): Boolean {
85+ val sm2Signer = SM2Signer ()
86+ val param = publicKey.hex2ByteArray().toECPublicKeyParams()
87+ sm2Signer.init (false , ParametersWithID (param, userId))
88+ sm2Signer.update(this , 0 , this .size)
89+ return sm2Signer.verifySignature(signed)
90+ }
91+
6192private fun generatePrivateKeyParameter (key : PrivateKey ): AsymmetricKeyParameter =
6293 when (key) {
6394 is ECPrivateKey -> {
@@ -82,10 +113,12 @@ private fun generatePrivateKeyParameter(key: PrivateKey): AsymmetricKeyParameter
82113 ECPrivateKeyParameters (key.d, ECDomainParameters (s!! .curve, s.g, s.n, s.h, s.seed))
83114 }
84115 }
116+
85117 is java.security.interfaces.ECPrivateKey -> {
86118 val s = EC5Util .convertSpec(key.params)
87119 ECPrivateKeyParameters (key.s, ECDomainParameters (s.curve, s.g, s.n, s.h, s.seed))
88120 }
121+
89122 else -> {
90123 // see if we can build a key from key.getEncoded()
91124 val bytes = key.encoded
@@ -100,13 +133,15 @@ private fun generatePublicKeyParameter(key: PublicKey): AsymmetricKeyParameter =
100133 val s = key.parameters
101134 ECPublicKeyParameters (key.q, ECDomainParameters (s.curve, s.g, s.n, s.h, s.seed))
102135 }
136+
103137 is java.security.interfaces.ECPublicKey -> {
104138 val s = EC5Util .convertSpec(key.params)
105139 ECPublicKeyParameters (
106140 EC5Util .convertPoint(key.params, key.w),
107141 ECDomainParameters (s.curve, s.g, s.n, s.h, s.seed),
108142 )
109143 }
144+
110145 else -> {
111146 // see if we can build a key from key.getEncoded()
112147 val bytes = key.encoded
0 commit comments