SM2椭圆曲线公钥密码算法:我国自主知识产权的商用密码算法,是ECC(Elliptic Curve Cryptosystem)算法的一种,基于椭圆曲线离散对数问题,计算复杂度是指数级,求解难度较大,同等安全程度要求下,椭圆曲线密码较其他公钥算法所需密钥长度小很多。

ECC算法描述:

1、用户A选定一条适合加密的椭圆曲线Ep(a,b)(如:y2=x3+ax+b),并取椭圆曲线上一点,作为基点G。

2、用户A选择一个私有密钥k,并生成公开密钥(公钥PB)K=kG。

3、用户A将Ep(a,b)和点(公钥)K,G传给用户B。

4、用户B接到信息后 ,将待传输的明文(M)编码到Ep(a,b)上一点M,并产生一个随机整数r(r

5、用户B计算点C1=M+rK;C2=rG。

6、用户B将C1、C2传给用户A。

7、用户A接到信息后,计算C1-kC2,结果就是点M。因为C1-kC2=M+rK-k(rG)=M+rK-r(kG)=M

再对点M进行解码就可以得到明文。

密码学中,描述一条Fp上的椭圆曲线,常用到六个参量:

T=(p,a,b,G,n,h)。

(p 、a 、b 用来确定一条椭圆曲线,G为基点,n为点G的阶,h 是椭圆曲线上所有点的个数m与n相除的整数部分)

这几个参量取值的选择,直接影响了加密的安全性。参量值一般要求满足以下几个条件:

1、p 当然越大越安全,但越大,计算速度会变慢,200位左右可以满足一般安全要求;

2、p≠n×h;

3、pt≠1 (mod n),1≤t<20;

4、4a3+27b2≠0 (mod p);

5、n 为素数;

6、h≤4。

轻量级密码术包(BouncyCastle):

一种用于 Java 平台的开放源码的轻量级密码术包;它支持大量的密码术算法,并提供JCE 1.2.1的实现。

bcprov-ext-jdk15on-160.jar

This release adds support for SHA-3 signatures to CMS, support for the Unified Model of Diffie-Hellman, and a parser for the GNU keybox format. PGP EC operations now support a wider range of curves, the BCJSSE now supports SNI, support has been added for generating ECGOST key transport messages and key wrapping ciphers can now also be used for wrapping general data. Initial low-level support has also been added for EdDSA. In terms of bugs fixed: RSA key pair generation with adjusted certainty values now conforms fully with FIPS PUB 186-4, the CRMF EncryptedValue field now encodes the encrypted value correctly without including the wrapping structure from the encryption, XMSS now validates any private key BDS data before construction, the SM2 signature now fully resets on a sign() call, and PGP secret keys with a null encryptor now calculate the correct checksum. An off by one error in the EST JsseDefaultHostnameAuthorizer valid name matcher has also been fixed. Further details on other additions and bug fixes can be found in the release notes file accompanying the release.

pom.xml

1

2

3

4

5

org.bouncycastle

bcprov-jdk15on

1.60

代码案例:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28package com.what21.demo.bouncycastle;

import java.math.BigInteger;

import org.bouncycastle.math.ec.ECPoint;

public class SM2KeyPair {

/** 公钥 */

private  ECPoint publicKey;

/** 私钥 */

private BigInteger privateKey;

SM2KeyPair(ECPoint publicKey, BigInteger privateKey) {

this.publicKey = publicKey;

this.privateKey = privateKey;

}

public ECPoint getPublicKey() {

return publicKey;

}

public BigInteger getPrivateKey() {

return privateKey;

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278package com.what21.demo.bouncycastle;

import java.math.BigInteger;

import java.security.SecureRandom;

import java.util.Arrays;

import org.bouncycastle.crypto.DerivationFunction;

import org.bouncycastle.crypto.digests.SHA256Digest;

import org.bouncycastle.crypto.digests.ShortenedDigest;

import org.bouncycastle.crypto.generators.KDF1BytesGenerator;

import org.bouncycastle.crypto.params.ISO18033KDFParameters;

import org.bouncycastle.math.ec.ECCurve;

import org.bouncycastle.math.ec.ECPoint;

public class SM2Utils {

/** 素数p */

private static final BigInteger p =new BigInteger("FFFFFFFE" +"FFFFFFFF"

+"FFFFFFFF" +"FFFFFFFF" +"FFFFFFFF" +"00000000" +"FFFFFFFF"

+"FFFFFFFF",16);

/** 系数a */

private static final BigInteger a =new BigInteger("FFFFFFFE" +"FFFFFFFF"

+"FFFFFFFF" +"FFFFFFFF" +"FFFFFFFF" +"00000000" +"FFFFFFFF"

+"FFFFFFFC",16);

/** 系数b */

private static final BigInteger b =new BigInteger("28E9FA9E" +"9D9F5E34"

+"4D5A9E4B" +"CF6509A7" +"F39789F5" +"15AB8F92" +"DDBCBD41"

+"4D940E93",16);

/** 坐标x */

private static final BigInteger xg =new BigInteger("32C4AE2C" +"1F198119"

+"5F990446" +"6A39C994" +"8FE30BBF" +"F2660BE1" +"715A4589"

+"334C74C7",16);

/** 坐标y */

private static final BigInteger yg =new BigInteger("BC3736A2" +"F4F6779C"

+"59BDCEE3" +"6B692153" +"D0A9877C" +"C62A4740" +"02DF32E5"

+"2139F0A0",16);

/** 基点G, G=(xg,yg),其介记为n */

private static final BigInteger n =new BigInteger("FFFFFFFE" +"FFFFFFFF"

+"FFFFFFFF" +"FFFFFFFF" +"7203DF6B" +"21C6052B" +"53BBF409"

+"39D54123",16);

private static SecureRandom random =new SecureRandom();

private ECCurve.Fp curve;

private ECPoint G;

@SuppressWarnings("deprecation")

public SM2Utils() {

curve =new ECCurve.Fp(p,// q

a,// a

b);// b

G = curve.createPoint(xg, yg);

}

public static String printHexString(byte[] b) {

StringBuilder builder =new StringBuilder();

for (int i =0; i

String hex = Integer.toHexString(b[i] &0xFF);

if (hex.length() ==1) {

builder.append('0'+hex);

hex ='0' + hex;

}

//System.out.print(hex.toUpperCase());

//System.out.print(hex.toUpperCase());

builder.append(hex);

}

//System.out.println();

return builder.toString();

}

public BigInteger random(BigInteger max) {

BigInteger r =new BigInteger(256, random);

// int count = 1;

while (r.compareTo(max) >=0) {

r =new BigInteger(128, random);

// count++;

}

// System.out.println("count: " + count);

return r;

}

private boolean allZero(byte[] buffer) {

for (int i =0; i

if (buffer[i] !=0)

return false;

}

return true;

}

/**

* 加密

* @param input 待加密消息M

* @param publicKey 公钥

* @return byte[] 加密后的字节数组

*/

public byte[] encrypt(String input, ECPoint publicKey) {

//System.out.println("publicKey is: "+publicKey);

byte[] inputBuffer = input.getBytes();

//printHexString(inputBuffer);

/* 1 产生随机数k,k属于[1, n-1] */

BigInteger k = random(n);

//System.out.print("k: ");

printHexString(k.toByteArray());

/* 2 计算椭圆曲线点C1 = [k]G = (x1, y1) */

ECPoint C1 = G.multiply(k);

byte[] C1Buffer = C1.getEncoded(false);

//System.out.print("C1: ");

printHexString(C1Buffer);

// 3 计算椭圆曲线点 S = [h]Pb * curve没有指定余因子,h为空

//           BigInteger h = curve.getCofactor(); System.out.print("h: ");

//           printHexString(h.toByteArray()); if (publicKey != null) { ECPoint

//           result = publicKey.multiply(h); if (!result.isInfinity()) {

//           System.out.println("pass"); } else {

//          System.err.println("计算椭圆曲线点 S = [h]Pb失败"); return null; } }

/* 4 计算 [k]PB = (x2, y2) */

ECPoint kpb = publicKey.multiply(k).normalize();

/* 5 计算 t = KDF(x2||y2, klen) */

byte[] kpbBytes = kpb.getEncoded(false);

DerivationFunction kdf = new KDF1BytesGenerator(new ShortenedDigest(

new SHA256Digest(), 20));

byte[] t = new byte[inputBuffer.length];

kdf.init(new ISO18033KDFParameters(kpbBytes));

kdf.generateBytes(t, 0, t.length);

if (allZero(t)) {

//System.err.println("all zero");

}

/* 6 计算C2=M^t */

byte[] C2 = new byte[inputBuffer.length];

for (int i = 0; i

C2[i] = (byte) (inputBuffer[i] ^ t[i]);

}

/* 7 计算C3 = Hash(x2 || M || y2) */

byte[] C3 = calculateHash(kpb.getXCoord().toBigInteger(), inputBuffer,

kpb.getYCoord().toBigInteger());

/* 8 输出密文 C=C1 || C2 || C3 */

byte[] encryptResult = new byte[C1Buffer.length + C2.length + C3.length];

System.arraycopy(C1Buffer, 0, encryptResult, 0, C1Buffer.length);

System.arraycopy(C2, 0, encryptResult, C1Buffer.length, C2.length);

System.arraycopy(C3, 0, encryptResult, C1Buffer.length + C2.length,

C3.length);

//System.out.print("密文: ");

// printHexString(encryptResult);

return encryptResult;

}

public byte[] decrypt(byte[] encryptData, BigInteger privateKey) {

//System.out.println("privateKey is: "+privateKey);

//System.out.println("encryptData length: " + encryptData.length);

byte[] C1Byte = new byte[65];

System.arraycopy(encryptData, 0, C1Byte, 0, C1Byte.length);

ECPoint C1 = curve.decodePoint(C1Byte).normalize();

/* 计算[dB]C1 = (x2, y2) */

ECPoint dBC1 = C1.multiply(privateKey).normalize();

/* 计算t = KDF(x2 || y2, klen) */

byte[] dBC1Bytes = dBC1.getEncoded(false);

DerivationFunction kdf = new KDF1BytesGenerator(new ShortenedDigest(

new SHA256Digest(), 20));

int klen = encryptData.length - 65 - 20;

//System.out.println("klen = " + klen);

byte[] t = new byte[klen];

kdf.init(new ISO18033KDFParameters(dBC1Bytes));

kdf.generateBytes(t, 0, t.length);

if (allZero(t)) {

//System.err.println("all zero");

}

/* 5 计算M'=C2^t */

byte[] M = new byte[klen];

for (int i = 0; i

M[i] = (byte) (encryptData[C1Byte.length + i] ^ t[i]);

}

/* 6 计算 u = Hash(x2 || M' || y2) 判断 u == C3是否成立 */

byte[] C3 = new byte[20];

System.arraycopy(encryptData, encryptData.length - 20, C3, 0, 20);

byte[] u = calculateHash(dBC1.getXCoord().toBigInteger(), M, dBC1.getYCoord().toBigInteger());

if (Arrays.equals(u, C3)) {

//System.out.println("解密成功");

//System.out.println("M' = " + new String(M));

return M;

} else {

//System.out.print("u = ");

//printHexString(u);

//System.out.print("C3 = ");

//printHexString(C3);

//System.err.println("解密验证失败");

}

return null;

}

private byte[] calculateHash(BigInteger x2, byte[] M, BigInteger y2) {

ShortenedDigest digest = new ShortenedDigest(new SHA256Digest(), 20);

byte[] buf = x2.toByteArray();

digest.update(buf, 0, buf.length);

digest.update(M, 0, M.length);

buf = y2.toByteArray();

digest.update(buf, 0, buf.length);

buf = new byte[20];

digest.doFinal(buf, 0);

return buf;

}

private boolean between(BigInteger param, BigInteger min, BigInteger max) {

if (param.compareTo(min) >= 0 && param.compareTo(max)

return true;

} else {

return false;

}

}

/**

* 公钥校验

* @param publicKey 公钥

* @return boolean true或false

*/

private boolean checkPublicKey(ECPoint publicKey) {

if (!publicKey.isInfinity()) {

BigInteger x = publicKey.getXCoord().toBigInteger();

BigInteger y = publicKey.getYCoord().toBigInteger();

if (between(x, new BigInteger("0"), p) && between(y, new BigInteger("0"), p)) {

BigInteger xResult = x.pow(3).add(a.multiply(x)).add(b).mod(p);

//System.out.println("xResult: " + xResult.toString());

BigInteger yResult = y.pow(2).mod(p);

//System.out.println("yResult: " + yResult.toString());

if (yResult.equals(xResult) && publicKey.multiply(n).isInfinity()) {

return true;

}

}

return false;

} else {

return false;

}

}

/**

* 获得公私钥对

* @return

*/

public SM2KeyPair generateKeyPair() {

BigInteger d = random(n.subtract(new BigInteger("1")));

SM2KeyPair keyPair =new SM2KeyPair(G.multiply(d).normalize(), d);

if (checkPublicKey(keyPair.getPublicKey())) {

//System.out.println("generate key successfully");

return keyPair;

}else {

//System.err.println("generate key failed");

return null;

}

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21package com.what21.demo.bouncycastle;

import java.util.Arrays;

public class App {

/**

* @param args

*/

public static void main(String[] args) {

SM2Utils sm2 =new SM2Utils();

SM2KeyPair keyPair = sm2.generateKeyPair();

String text ="小奋斗{www.what21.com}";

System.out.println("文本为:" + text);

byte[] data = sm2.encrypt(text,keyPair.getPublicKey());

System.out.println("加密为:"+Arrays.toString(data));

byte[] data2 = sm2.decrypt(data, keyPair.getPrivateKey());

System.out.println("解密为:" +new String(data2));

}

}

程序输入:

1

2

3文本为:小奋斗{www.what21.com}

加密为:[4, 66, 87, 4, -112, -103, 73, -79, -26, -2, 50, 110, -45, 119, -63, -94, 70, -24, 111, 93, 79, 47, 2, 92, -118, -65, -87, -20, 12, 43, -121, 20, -39, -35, -27, 4, 20, 103, 26, 89, 48, -95, -64, -6, 93, -35, 69, 63, -64, -119, -14, 65, 11, 24, 43, -119, 50, 89, 60, 15, 61, 83, 33, -90, 5, -44, -107, -118, 98, 0, -12, 10, 0, -73, 41, -91, 69, 106, 100, 109, 117, 99, 31, 97, 127, -120, 64, -76, 52, 98, -52, -79, 96, 19, -71, -100, -111, -93, 113, 45, 92, 105, 46, 124, -19, -66, -102, 106, 2, 75]

解密为:小奋斗{www.what21.com}

java判断对称素数_SM2非对称算法的原理及实现 Java SM2的代码案例 | 一生孤注掷温柔 | 小奋斗...相关推荐

  1. Miller_Rabbin算法判断大素数,Pollard_rho算法进行质因素分解

    Miller-rabin算法是一个用来快速判断一个正整数是否为素数的算法.它利用了费马小定理,即:如果p是质数,且a,p互质,那么a^(p-1) mod p恒等于1.也就是对于所有小于p的正整数a来说 ...

  2. [数论] Miller_Rabbin算法判断大素数,Pollard_rho算法进行质因素分解

    讲解转载于:http://www.cnblogs.com/rainydays/archive/2011/09/01/2162049.html   http://blog.sina.com.cn/s/b ...

  3. java判断邮箱名和文件名_Java公开课|想学好Java,教你操作Java校验文件名和邮箱地址,快来看看...

    [摘要]作为一门面向对象编程语言,Java吸收了C++语言的优点,也展现了其强大的一面,我们能在各个地方看到其功能强大和简单易用的两个特征,当然,也吸引了很多程序员的注意力,所以就有人想了解Java的 ...

  4. 【Java基础】HashMap扩容 | CopyOnWriteArrayList 的底层原理 | 字节码 | Java 异常体系

    1. HashMap的扩容机制 JDK 1.7 扩容是针对数组进行扩容,链表是不需要进行扩容的.扩容时先生成原来数组两倍大小的新数组,在把原来老数组上的链表上的元素转移过去.具体在转移链表中元素的步骤 ...

  5. java判断五位数回文数_【视频+图文】Java经典基础练习题(五):键盘输入一个五位数,判断这个数是否为回文数...

    能解决题目的代码并不是一次就可以写好的 我们需要根据我们的思路写出后通过debug模式找到不足再进行更改 多次测试后才可得到能解决题目的代码! 通过学习,练习[Java基础经典练习题],让我们一起来培 ...

  6. 对称加密和非对称加密的原理

    对称加密:加密和解密使用的是同一把密钥.加密:原文+密钥=密文   解密:密文-密钥=原文 非对称加密:非对称加密有两把密钥即公钥和私钥,公钥和私钥是成对存在的,如果使用公钥加密,使用对应的私钥才能解 ...

  7. java关于hashmap编程题_LeetCode算法题-Design HashMap(Java实现)

    这是悦乐书的第299次更新,第318篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第167题(顺位题号是706).在不使用任何内置哈希表库的情况下设计HashMap.具体 ...

  8. java 判断文件是否打开过_【后端开发】Java中如何判断文件是否被隐藏?(代码示例)...

    在Java中我们可以使用File类的isHidden()方法来判断指定文件是否被隐藏:下面本篇文章就来带大家认识一下isHidden()方法,了解如何使用isHidden()方法来判断文件是否被隐藏, ...

  9. 雪花算法的原理和实现Java

    SnowFlake 算法,是 Twitter 开源的分布式 id 生成算法.其核心思想就是:使用一个 64 bit 的 long 型的数字作为全局唯一 id.在分布式系统中的应用十分广泛,且ID 引入 ...

最新文章

  1. 北京铁路局百余列普速列车将开通WiFi
  2. Tungsten Fabric SDN — 网络协议
  3. 027_html框架
  4. jvm性能调优 - 13JVM的年轻代垃圾回收器ParNew原理
  5. Oracle如何监控表的DML次数
  6. 如何找到某个 ABAP structure 某字段的源头来自哪个数据库表
  7. sign check fail: check Sign and Data Fail!-错误处理
  8. Python数据可视化-matplotlib and seaborn
  9. IDA pro 的Python环境变量设置
  10. 论文Real-Time Lane and Obstacle Detection on the global System
  11. python之绘制图形库turtle
  12. Mac删除并合并windows分区解决办法
  13. eset杀毒软件隔离区在哪里
  14. 用matlab机器人工具箱对SCARA机器人建模
  15. Scott Page  斯科特佩奇《模型思维》读书笔记
  16. 阿里热更新hotfix
  17. java怎么绘画坦克_java绘图,画坦克
  18. 英语中表示同意或肯定的词
  19. 京东网页(动态)搭建,利用jquery实现
  20. 欧氏距离 VS 余弦距离

热门文章

  1. docker mysql:8.0.27
  2. editor.md 实现拖拽剪切复制粘贴上传图片,文件插件
  3. linux 添加sftp用户
  4. 第七篇:Spring Boot 整合_Thymeleaf 入门试炼 QuickStart
  5. Excel 表单控件之 CheckBox 集合事件响应
  6. python中with是什么意思_python中with的用法
  7. vs2010中引入boost库
  8. qt自定义行编辑器,用来加载颜色
  9. Qt中UDP通信的简单示例
  10. linux真实地址是什么意思,linux – 如何为发件人地址配置真实域名