package com.crypto.gm;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
/**
* 如果使用bcprov-jdk15on包的实现,需要将算法注册到JDK中,然后通过Cipher cipher = Cipher.getInstance("SM4/ECB/PKCS5Padding")来加密。
* 加密算法注册到JDK中要求JAR有签名,这个签名方式在不同JDK怎么本中有兼容性问题,比如bcprov-jdk15on-1.61及以上版本的签名不支持JDK1.6
*
* 基于以上原因,本类SM4改为不依赖bcprov-jdk15on包,算法代码下载自网络
*
*/
public class SM4Util {
private static final byte[] S_BOX_TABLE = { (byte) 0xd6, (byte) 0x90, (byte) 0xe9, (byte) 0xfe, (byte) 0xcc,
(byte) 0xe1, 0x3d, (byte) 0xb7, 0x16, (byte) 0xb6, 0x14, (byte) 0xc2, 0x28, (byte) 0xfb, 0x2c, 0x05, 0x2b,
0x67, (byte) 0x9a, 0x76, 0x2a, (byte) 0xbe, 0x04, (byte) 0xc3, (byte) 0xaa, 0x44, 0x13, 0x26, 0x49,
(byte) 0x86, 0x06, (byte) 0x99, (byte) 0x9c, 0x42, 0x50, (byte) 0xf4, (byte) 0x91, (byte) 0xef,
(byte) 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, (byte) 0xed, (byte) 0xcf, (byte) 0xac, 0x62, (byte) 0xe4,
(byte) 0xb3, 0x1c, (byte) 0xa9, (byte) 0xc9, 0x08, (byte) 0xe8, (byte) 0x95, (byte) 0x80, (byte) 0xdf,
(byte) 0x94, (byte) 0xfa, 0x75, (byte) 0x8f, 0x3f, (byte) 0xa6, 0x47, 0x07, (byte) 0xa7, (byte) 0xfc,
(byte) 0xf3, 0x73, 0x17, (byte) 0xba, (byte) 0x83, 0x59, 0x3c, 0x19, (byte) 0xe6, (byte) 0x85, 0x4f,
(byte) 0xa8, 0x68, 0x6b, (byte) 0x81, (byte) 0xb2, 0x71, 0x64, (byte) 0xda, (byte) 0x8b, (byte) 0xf8,
(byte) 0xeb, 0x0f, 0x4b, 0x70, 0x56, (byte) 0x9d, 0x35, 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, (byte) 0xd1,
(byte) 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, (byte) 0x87, (byte) 0xd4, 0x00, 0x46, 0x57,
(byte) 0x9f, (byte) 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, (byte) 0xe7, (byte) 0xa0, (byte) 0xc4, (byte) 0xc8,
(byte) 0x9e, (byte) 0xea, (byte) 0xbf, (byte) 0x8a, (byte) 0xd2, 0x40, (byte) 0xc7, 0x38, (byte) 0xb5,
(byte) 0xa3, (byte) 0xf7, (byte) 0xf2, (byte) 0xce, (byte) 0xf9, 0x61, 0x15, (byte) 0xa1, (byte) 0xe0,
(byte) 0xae, 0x5d, (byte) 0xa4, (byte) 0x9b, 0x34, 0x1a, 0x55, (byte) 0xad, (byte) 0x93, 0x32, 0x30,
(byte) 0xf5, (byte) 0x8c, (byte) 0xb1, (byte) 0xe3, 0x1d, (byte) 0xf6, (byte) 0xe2, 0x2e, (byte) 0x82,
0x66, (byte) 0xca, 0x60, (byte) 0xc0, 0x29, 0x23, (byte) 0xab, 0x0d, 0x53, 0x4e, 0x6f, (byte) 0xd5,
(byte) 0xdb, 0x37, 0x45, (byte) 0xde, (byte) 0xfd, (byte) 0x8e, 0x2f, 0x03, (byte) 0xff, 0x6a, 0x72, 0x6d,
0x6c, 0x5b, 0x51, (byte) 0x8d, 0x1b, (byte) 0xaf, (byte) 0x92, (byte) 0xbb, (byte) 0xdd, (byte) 0xbc, 0x7f,
0x11, (byte) 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, (byte) 0xd8, 0x0a, (byte) 0xc1, 0x31, (byte) 0x88,
(byte) 0xa5, (byte) 0xcd, 0x7b, (byte) 0xbd, 0x2d, 0x74, (byte) 0xd0, 0x12, (byte) 0xb8, (byte) 0xe5,
(byte) 0xb4, (byte) 0xb0, (byte) 0x89, 0x69, (byte) 0x97, 0x4a, 0x0c, (byte) 0x96, 0x77, 0x7e, 0x65,
(byte) 0xb9, (byte) 0xf1, 0x09, (byte) 0xc5, 0x6e, (byte) 0xc6, (byte) 0x84, 0x18, (byte) 0xf0, 0x7d,
(byte) 0xec, 0x3a, (byte) 0xdc, 0x4d, 0x20, 0x79, (byte) 0xee, 0x5f, 0x3e, (byte) 0xd7, (byte) 0xcb, 0x39,
0x48 };
private static final int[] FK = { 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc };
private static final int[] CK = { 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, 0x70777e85, 0x8c939aa1,
0xa8afb6bd, 0xc4cbd2d9, 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, 0x50575e65, 0x6c737a81, 0x888f969d,
0xa4abb2b9, 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279 };
private static long getUlongBE(byte[] b, int i) {
long n = (long) (b[i] & 0xff) << 24 | (long) ((b[i + 1] & 0xff) << 16) | (long) ((b[i + 2] & 0xff) << 8)
| (long) (b[i + 3] & 0xff) & 0xffffffffL;
return n;
}
private static void putUlongBE(long n, byte[] b, int i) {
b[i] = (byte) (int) (0xFF & n >> 24);
b[i + 1] = (byte) (int) (0xFF & n >> 16);
b[i + 2] = (byte) (int) (0xFF & n >> 8);
b[i + 3] = (byte) (int) (0xFF & n);
}
private static long rotl(long x, int n) {
long shl = (x & 0xFFFFFFFF) << n;
return shl | x >> (32 - n);
}
private static long sm4Lt(long ka) {
long bb = 0L;
long c = 0L;
byte[] a = new byte[4];
byte[] b = new byte[4];
putUlongBE(ka, a, 0);
b[0] = sm4Sbox(a[0]);
b[1] = sm4Sbox(a[1]);
b[2] = sm4Sbox(a[2]);
b[3] = sm4Sbox(a[3]);
bb = getUlongBE(b, 0);
c = bb ^ rotl(bb, 2) ^ rotl(bb, 10) ^ rotl(bb, 18) ^ rotl(bb, 24);
return c;
}
private static long sm4F(long x0, long x1, long x2, long x3, long rk) {
return x0 ^ sm4Lt(x1 ^ x2 ^ x3 ^ rk);
}
private static long sm4CalciRK(long ka) {
long bb = 0L;
long rk = 0L;
byte[] a = new byte[4];
byte[] b = new byte[4];
putUlongBE(ka, a, 0);
b[0] = sm4Sbox(a[0]);
b[1] = sm4Sbox(a[1]);
b[2] = sm4Sbox(a[2]);
b[3] = sm4Sbox(a[3]);
bb = getUlongBE(b, 0);
rk = bb ^ rotl(bb, 13) ^ rotl(bb, 23);
return rk;
}
private static byte sm4Sbox(byte inch) {
int i = inch & 0xFF;
byte retVal = S_BOX_TABLE[i];
return retVal;
}
private static long[] sm4SetKey(byte[] key, boolean encryptMode) {
long[] sk = new long[32];
long[] mk = new long[4];
long[] k = new long[36];
mk[0] = getUlongBE(key, 0);
mk[1] = getUlongBE(key, 4);
mk[2] = getUlongBE(key, 8);
mk[3] = getUlongBE(key, 12);
k[0] = mk[0] ^ (long) FK[0];
k[1] = mk[1] ^ (long) FK[1];
k[2] = mk[2] ^ (long) FK[2];
k[3] = mk[3] ^ (long) FK[3];
for (int i = 0; i < 32; i++) {
k[(i + 4)] = (k[i] ^ sm4CalciRK(k[(i + 1)] ^ k[(i + 2)] ^ k[(i + 3)] ^ (long) CK[i]));
sk[i] = k[(i + 4)];
}
if (!encryptMode) {
for (int i = 0; i < 16; i++) {
long t = sk[i];
sk[i] = sk[(31 - i)];
sk[(31 - i)] = t;
}
}
return sk;
}
private static byte[] padding(byte[] input, boolean encryptMode) {
if (input == null) {
return null;
}
byte[] ret = (byte[]) null;
if (encryptMode) {
int p = 16 - input.length % 16;
ret = new byte[input.length + p];
System.arraycopy(input, 0, ret, 0, input.length);
for (int i = 0; i < p; i++) {
ret[input.length + i] = (byte) p;
}
} else {
int p = input[input.length - 1];
ret = new byte[input.length - p];
System.arraycopy(input, 0, ret, 0, input.length - p);
}
return ret;
}
private static void sm4OneRound(long[] sk, byte[] input, byte[] output) {
int i = 0;
long[] ulbuf = new long[36];
ulbuf[0] = getUlongBE(input, 0);
ulbuf[1] = getUlongBE(input, 4);
ulbuf[2] = getUlongBE(input, 8);
ulbuf[3] = getUlongBE(input, 12);
while (i < 32) {
ulbuf[(i + 4)] = sm4F(ulbuf[i], ulbuf[(i + 1)], ulbuf[(i + 2)], ulbuf[(i + 3)], sk[i]);
i++;
}
putUlongBE(ulbuf[35], output, 0);
putUlongBE(ulbuf[34], output, 4);
putUlongBE(ulbuf[33], output, 8);
putUlongBE(ulbuf[32], output, 12);
}
public static byte[] cryptEcb(byte[] key, byte[] input, boolean encryptMode, boolean isPadding) {
if (key == null || key.length != 16) {
throw new IllegalArgumentException("key error!");
}
if (input == null) {
throw new IllegalArgumentException("input is null!");
}
long[] sk = sm4SetKey(key, encryptMode);
if (isPadding && encryptMode) {
input = padding(input, encryptMode);
}
int length = input.length;
try {
ByteArrayInputStream bins = new ByteArrayInputStream(input);
ByteArrayOutputStream bous = new ByteArrayOutputStream();
for (; length > 0; length -= 16) {
byte[] in = new byte[16];
byte[] out = new byte[16];
bins.read(in);
sm4OneRound(sk, in, out);
bous.write(out);
}
byte[] output = bous.toByteArray();
if (isPadding && !encryptMode) {
output = padding(output, encryptMode);
}
bins.close();
bous.clos
没有合适的资源?快使用搜索试试~ 我知道了~
国密SM2、SM3、SM4算法(JS、Java版)
共26个文件
js:13个
java:6个
html:4个
5星 · 超过95%的资源 需积分: 46 111 下载量 178 浏览量
2018-11-02
16:32:35
上传
评论 4
收藏 3.49MB ZIP 举报
温馨提示
Java版是基于bcprov-jdk15on-1.60.jar的简单封装; Javascript版本的原始代码来源于网络,进行整合与改造,主要解决网络上版本中的SM4加密计算过程中位溢出问题,SM2签名小概率出错问题; 特点:SM2、SM3、SM4的Java版本与Javascript版本可以相互加解密、相互签名验证。 收集下载JavaScript版本相关资料时,把分数都花光了,希望能把分数赚回来 ( ^_^ ) ---精简优化
资源推荐
资源详情
资源评论
收起资源包目录
SM1.1.zip (26个子文件)
SM
src
com
crypto
gm
SMHelper.java 6KB
SM2Keys.java 8KB
SM4Util.java 10KB
SM2Util.java 5KB
test
GMTest.java 9KB
SM3Util.java 966B
.classpath 367B
js
sm2.js 18KB
ec.js 9KB
utils.js 2KB
min
sm3-all-min.js 27KB
sm2-all-min.js 48KB
sm4-all-min.js 27KB
jsbn.js 15KB
prng4.js 1KB
jsbn2.js 18KB
rng.js 2KB
ec-patch.js 6KB
sm3.js 12KB
sm4.js 11KB
.project 378B
lib
bcprov-jdk15on-1.60.jar 4MB
demos
sm2.html 3KB
test.html 5KB
sm3.html 1KB
sm4.html 3KB
共 26 条
- 1
资源评论
- 大伟LAW2023-05-17支持国产SM算法,这个替代我原来的MD5算法。
- lvxianling2022-10-09#完美解决问题,可以使用,多谢分享。
- TYD1230132021-04-21SM4算法打包后运行会出现java.lang.SecurityException: JCE cannot authenticate the provider BCzhuoshiyao2021-07-21已更新
- xuan-0012020-12-19hah,辛苦,确实可用,很完整
zhuoshiyao
- 粉丝: 2
- 资源: 2
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功