临时存储
This commit is contained in:
14
build.gradle
14
build.gradle
@@ -15,8 +15,8 @@ sourceSets {
|
||||
/** 统一编译编码 */
|
||||
tasks.withType(JavaCompile).configureEach { t ->
|
||||
t.options.encoding = "UTF-8"
|
||||
t.sourceCompatibility = "1.5"
|
||||
t.targetCompatibility = "1.5"
|
||||
t.sourceCompatibility = "1.8"
|
||||
t.targetCompatibility = "1.8"
|
||||
def jcHome = System.getenv("JC_HOME")
|
||||
if (!jcHome) throw new GradleException("缺少 JC_HOME")
|
||||
t.options.bootstrapClasspath = files("${jcHome}/lib/api_classic.jar")
|
||||
@@ -34,10 +34,12 @@ dependencies {
|
||||
|
||||
/** ===== 用本地 JCDK converter 生成 CAP ===== */
|
||||
def pkgName = "com.zuc.zuc256" // ← 改成你的包名
|
||||
def appletClass = "${pkgName}.MyApplet" // ← 改成你的 Applet 全类名
|
||||
def appletClass = "${pkgName}.XwSecurity" // ← 改成你的 Applet 全类名
|
||||
def packageAID = "0xA0:0x00:0x00:0x03:0x33:0x01:0x01" // ← 改成你的包 AID
|
||||
def appletAID = "0xA0:0x00:0x00:0x03:0x33:0x01:0x01:0x01"// ← 改成你的实例 AID
|
||||
def ver = "1.0"
|
||||
|
||||
|
||||
tasks.register("buildCap") {
|
||||
group = "build"
|
||||
description = "Generate CAP via JCDK converter.bat"
|
||||
@@ -61,7 +63,7 @@ tasks.register("buildCap") {
|
||||
if (!batFile.exists()) throw new GradleException("未找到 converter.bat:${batFile}")
|
||||
|
||||
// 确认 .class 存在
|
||||
def cls = file("$buildDir/classes/java/main/${pkgName.replace('.','/')}/MyApplet.class")
|
||||
def cls = file("$buildDir/classes/java/main/${pkgName.replace('.','/')}/XwSecurity.class")
|
||||
if (!cls.exists()) throw new GradleException("未找到已编译类:${cls}")
|
||||
|
||||
|
||||
@@ -96,7 +98,7 @@ tasks.register("buildCap") {
|
||||
|
||||
if (result.exitValue != 0) {
|
||||
println "---- converter.log tail ----"
|
||||
println logFile.readLines("GBK").takeRight(80).join(System.lineSeparator())
|
||||
println logFile.readLines("UTF-8").takeRight(80).join(System.lineSeparator())
|
||||
throw new GradleException("converter 退出码:${result.exitValue}")
|
||||
} else {
|
||||
println "CAP 生成成功,目录:${file("$buildDir/javacard").absolutePath}"
|
||||
@@ -104,3 +106,5 @@ tasks.register("buildCap") {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
3
gradle.properties
Normal file
3
gradle.properties
Normal file
@@ -0,0 +1,3 @@
|
||||
# 统一 Gradle/JVM 的默认编码
|
||||
org.gradle.jvmargs=-Xmx2g -Dfile.encoding=UTF-8
|
||||
systemProp.file.encoding=UTF-8
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -3,5 +3,3 @@ distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.4-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
org.gradle.jvmargs=-Dfile.encoding=UTF-8
|
||||
org.gradle.console=plain
|
||||
|
||||
19
src/com/zuc/zuc256/Method.java
Normal file
19
src/com/zuc/zuc256/Method.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package com.zuc.zuc256;
|
||||
|
||||
import javacard.framework.APDU;
|
||||
|
||||
public class Method {
|
||||
|
||||
public void processData(APDU apdu)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public void updateKey(APDU apdu)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package com.zuc.zuc256;
|
||||
|
||||
import javacard.framework.*;
|
||||
|
||||
/**
|
||||
* 最小 JavaCard Applet 示例
|
||||
*/
|
||||
public class MyApplet extends Applet {
|
||||
|
||||
// 构造函数:一般初始化状态
|
||||
protected MyApplet() {
|
||||
register(); // 必须调用,完成注册
|
||||
}
|
||||
|
||||
// 安装方法:CAP 文件安装时调用
|
||||
public static void install(byte[] bArray, short bOffset, byte bLength) {
|
||||
new MyApplet();
|
||||
}
|
||||
|
||||
// 处理 APDU 命令
|
||||
@Override
|
||||
public void process(APDU apdu) throws ISOException {
|
||||
if (selectingApplet()) {
|
||||
return; // 选择时无需处理数据
|
||||
}
|
||||
// 默认:所有指令不支持
|
||||
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
|
||||
}
|
||||
}
|
||||
81
src/com/zuc/zuc256/XwSecurity.java
Normal file
81
src/com/zuc/zuc256/XwSecurity.java
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package com.zuc.zuc256;
|
||||
|
||||
|
||||
import javacard.framework.Applet;
|
||||
import javacard.framework.ISOException;
|
||||
import javacard.framework.ISO7816;
|
||||
import javacard.framework.APDU;
|
||||
|
||||
/**
|
||||
* @author liuww
|
||||
*
|
||||
*/
|
||||
public class XwSecurity extends Applet {
|
||||
|
||||
public static final byte INS_PROCESS_DATA = (byte)0xCA;
|
||||
|
||||
public static final byte INS_STORE_DATA = (byte)0xE2;
|
||||
|
||||
public static final byte INS_INITIAL_UPDATE = (byte)0x50;
|
||||
|
||||
public static final byte INS_EXTERNAL_AUTH = (byte)0x82;
|
||||
|
||||
private Method method;
|
||||
|
||||
public XwSecurity(byte[] bArray, short bOffset, byte bLength) {
|
||||
// TODO Auto-generated constructor stub
|
||||
method = new Method();
|
||||
|
||||
register(bArray, (short)(bOffset + 1), bArray[bOffset]);
|
||||
}
|
||||
|
||||
public static void install(byte[] bArray, short bOffset, byte bLength)
|
||||
{
|
||||
// GP-compliant JavaCard applet registration
|
||||
new XwSecurity(bArray, bOffset, bLength);
|
||||
}
|
||||
|
||||
public void process(APDU apdu)
|
||||
{
|
||||
// Good practice: Return 9000 on SELECT
|
||||
if(selectingApplet())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(method == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] buf = apdu.getBuffer();
|
||||
switch (buf[ISO7816.OFFSET_INS])
|
||||
{
|
||||
case INS_INITIAL_UPDATE:
|
||||
// SecureChannel sc = GPSystem.getSecureChannel();
|
||||
// sc.processSecurity(apdu);
|
||||
break;
|
||||
|
||||
case INS_EXTERNAL_AUTH:
|
||||
// sc = GPSystem.getSecureChannel();
|
||||
// sc.processSecurity(apdu);
|
||||
break;
|
||||
|
||||
case INS_PROCESS_DATA:
|
||||
method.processData(apdu);
|
||||
break;
|
||||
|
||||
case INS_STORE_DATA:
|
||||
method.updateKey(apdu);
|
||||
break;
|
||||
|
||||
default:
|
||||
// good practice: If you don't know the INStruction, say so:
|
||||
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,10 @@ public final class Zuc256Core {
|
||||
a = (a & 0x7FFFFFFF) + (a >>> 31);
|
||||
int v = (int) ((a & 0x7FFFFFFF) + (a >>> 31));
|
||||
|
||||
System.arraycopy(LFSR, 1, LFSR, 0, 15);
|
||||
// System.arraycopy(LFSR, 1, LFSR, 0, 15);
|
||||
for (short i = 0; i < 15; i++) {
|
||||
LFSR[i] = LFSR[i + 1];
|
||||
}
|
||||
LFSR[15] = v;
|
||||
|
||||
state.R1 = R1;
|
||||
@@ -119,7 +122,10 @@ public final class Zuc256Core {
|
||||
a = (a & 0x7FFFFFFF) + (a >>> 31);
|
||||
int v = (int) ((a & 0x7FFFFFFF) + (a >>> 31));
|
||||
|
||||
System.arraycopy(LFSR, 1, LFSR, 0, 15);
|
||||
// System.arraycopy(LFSR, 1, LFSR, 0, 15);
|
||||
for (short j = 0; j < (short)15; j++) {
|
||||
LFSR[j] = LFSR[(short)(j + 1)];
|
||||
}
|
||||
LFSR[15] = v;
|
||||
}
|
||||
|
||||
@@ -171,7 +177,11 @@ public final class Zuc256Core {
|
||||
a = (a & 0x7FFFFFFF) + (a >>> 31);
|
||||
int v = (int) ((a & 0x7FFFFFFF) + (a >>> 31));
|
||||
|
||||
System.arraycopy(LFSR, 1, LFSR, 0, 15);
|
||||
// System.arraycopy(LFSR, 1, LFSR, 0, 15);
|
||||
for (short i = 0; i < (short)15; i++) {
|
||||
LFSR[i] = LFSR[(short)(i + 1)];
|
||||
}
|
||||
|
||||
LFSR[15] = v;
|
||||
|
||||
state.R1 = R1;
|
||||
@@ -250,7 +260,10 @@ public final class Zuc256Core {
|
||||
v = add31(v, rot31(LFSR[15], 15));
|
||||
v = add31(v, W >>> 1);
|
||||
|
||||
System.arraycopy(LFSR, 1, LFSR, 0, 15);
|
||||
// System.arraycopy(LFSR, 1, LFSR, 0, 15);
|
||||
for (short j = 0; j < (short)15; j++) {
|
||||
LFSR[j] = LFSR[(short)(j + 1)];
|
||||
}
|
||||
LFSR[15] = v;
|
||||
}
|
||||
|
||||
@@ -284,7 +297,10 @@ public final class Zuc256Core {
|
||||
a = (a & 0x7FFFFFFF) + (a >>> 31);
|
||||
int v = (int) ((a & 0x7FFFFFFF) + (a >>> 31));
|
||||
|
||||
System.arraycopy(LFSR, 1, LFSR, 0, 15);
|
||||
// System.arraycopy(LFSR, 1, LFSR, 0, 15);
|
||||
for (short i = 0; i < (short)15; i++) {
|
||||
LFSR[i] = LFSR[(short)(i + 1)];
|
||||
}
|
||||
LFSR[15] = v;
|
||||
|
||||
key.R1 = R1;
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
package com.zuc.zuc256;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
import static com.zuc.zuc256.Zuc256Util.extractIv;
|
||||
import static com.zuc.zuc256.Zuc256Util.printHex;
|
||||
|
||||
|
||||
|
||||
@@ -12,22 +11,45 @@ import static com.zuc.zuc256.Zuc256Util.printHex;
|
||||
*/
|
||||
public final class Zuc256Demo {
|
||||
|
||||
public static void main(String[] args) {
|
||||
public static void main(short args[]) {
|
||||
// 1. 明文
|
||||
byte[] plaintext = "ZUC256对称加解密测试:1234567890".getBytes();
|
||||
int plaintextLen = plaintext.length;
|
||||
System.out.println("明文: " + new String(plaintext));
|
||||
printHex("明文(十六进制)", plaintext, plaintextLen);
|
||||
byte[] plaintext = new byte[] {
|
||||
0x5A, 0x55, 0x43, 0x32, 0x35, 0x36,
|
||||
(byte)0xE5,(byte)0xAF,(byte)0xB9,(byte)0xE7,(byte)0xA7,(byte)0xB0,
|
||||
(byte)0xE5,(byte)0x8A,(byte)0xA0,(byte)0xE8,(byte)0xA7,(byte)0xA3,
|
||||
(byte)0xE5,(byte)0xAF,(byte)0x86,(byte)0xE6,(byte)0xB5,(byte)0x8B,
|
||||
(byte)0xE8,(byte)0xAF,(byte)0x95, 0x3A,
|
||||
0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x30
|
||||
}; // 长度=38 ZUC256加密测试
|
||||
short plaintextLen = (short)plaintext.length;
|
||||
// System.out.println("明文: " + new String(plaintext));
|
||||
// printHex("明文(十六进制)", plaintext, plaintextLen);
|
||||
|
||||
// 2. 密钥(32字节ASCII)
|
||||
byte[] key = "0123456789abcdef0123456789abcdef".getBytes();
|
||||
printHex("密钥", key, 32);
|
||||
byte[] key = new byte[] {
|
||||
0x30, 0x31, 0x32, 0x33, // "0123"
|
||||
0x34, 0x35, 0x36, 0x37, // "4567"
|
||||
0x38, 0x39, 0x61, 0x62, // "89ab"
|
||||
0x63, 0x64, 0x65, 0x66, // "cdef"
|
||||
0x30, 0x31, 0x32, 0x33,
|
||||
0x34, 0x35, 0x36, 0x37,
|
||||
0x38, 0x39, 0x61, 0x62,
|
||||
0x63, 0x64, 0x65, 0x66
|
||||
};
|
||||
// byte[] key = "0123456789abcdef0123456789abcdef".getBytes();
|
||||
// printHex("密钥", key, 32);
|
||||
|
||||
// 3. 初始向量(25字节ASCII)
|
||||
byte[] inputIv25Byte = "0123456789abcdefg01234567".getBytes();
|
||||
// byte[] inputIv25Byte = "0123456789abcdefg01234567".getBytes();
|
||||
byte[] inputIv25Byte = new byte[] {
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, // "01234567"
|
||||
0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, // "89abcdef"
|
||||
0x67, // "g"
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 // "01234567"
|
||||
};
|
||||
byte[] iv = new byte[23];
|
||||
extractIv(inputIv25Byte, iv);
|
||||
printHex("提取后的IV", iv, 23);
|
||||
// printHex("提取后的IV", iv, 23);
|
||||
|
||||
// 4. 分配加密/解密缓冲区
|
||||
byte[] ciphertext = new byte[plaintextLen];
|
||||
@@ -37,25 +59,25 @@ public final class Zuc256Demo {
|
||||
Zuc256State stateEnc = new Zuc256State();
|
||||
Zuc256Core.initState(stateEnc, key, iv);
|
||||
zuc256Crypt(stateEnc, plaintext, plaintextLen, ciphertext);
|
||||
printHex("密文", ciphertext, plaintextLen);
|
||||
// printHex("密文", ciphertext, plaintextLen);
|
||||
|
||||
// 6. 解密(重新初始化状态)
|
||||
Zuc256State stateDec = new Zuc256State();
|
||||
Zuc256Core.initState(stateDec, key, iv);
|
||||
zuc256Crypt(stateDec, ciphertext, plaintextLen, decryptedtext);
|
||||
printHex("解密后", decryptedtext, plaintextLen);
|
||||
System.out.println("解密文本: " + new String(decryptedtext));
|
||||
// printHex("解密后", decryptedtext, plaintextLen);
|
||||
// System.out.println("解密文本: " + new String(decryptedtext));
|
||||
|
||||
// 7. 验证结果
|
||||
if (Arrays.equals(plaintext, decryptedtext)) {
|
||||
System.out.println("=== 测试成功: 解密结果与明文一致 ===");
|
||||
} else {
|
||||
System.out.println("=== 测试失败: 解密结果与明文不一致 ===");
|
||||
}
|
||||
// if (Arrays.equals(plaintext, decryptedtext)) {
|
||||
// System.out.println("=== 测试成功: 解密结果与明文一致 ===");
|
||||
// } else {
|
||||
// System.out.println("=== 测试失败: 解密结果与明文不一致 ===");
|
||||
// }
|
||||
}
|
||||
|
||||
// 一次性加密
|
||||
public static void zuc256Crypt(Zuc256State state, byte[] in, int inlen, byte[] out) {
|
||||
public static void zuc256Crypt(Zuc256State state, byte[] in, short inlen, byte[] out) {
|
||||
if (state == null || in == null || out == null) return;
|
||||
|
||||
Zuc256EncryptCtx ctx = new Zuc256EncryptCtx(state);
|
||||
@@ -68,6 +90,6 @@ public final class Zuc256Demo {
|
||||
System.arraycopy(out, remainingOffset, finishOut, 0, finishOut.length);
|
||||
}
|
||||
ctx.finish(finishOut);
|
||||
System.arraycopy(finishOut, 0, out, remainingOffset, finishOut.length);
|
||||
System.arraycopy(finishOut, (short)0, out, (short)remainingOffset, (short)finishOut.length);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.zuc.zuc256;
|
||||
|
||||
import java.util.Arrays;
|
||||
import javacard.framework.Util;
|
||||
|
||||
import static com.zuc.zuc256.Zuc256Core.zuc256GenerateKeystream;
|
||||
import static com.zuc.zuc256.Zuc256Core.zuc256GenerateKeyword;
|
||||
@@ -33,27 +33,32 @@ public final class Zuc256EncryptCtx {
|
||||
|
||||
// 初始化加密上下文
|
||||
public void init(byte[] key32, byte[] iv) {
|
||||
Arrays.fill(this.buf, (byte) 0);
|
||||
Util.arrayFillNonAtomic(this.buf, (short) 0, (short) this.buf.length, (byte) 0);
|
||||
this.buflen = 0;
|
||||
Zuc256Core.initState(this.state, key32, iv);
|
||||
}
|
||||
|
||||
// 分阶段处理加密数据
|
||||
public void update(byte[] in, int inlen, byte[] out) {
|
||||
public void update(byte[] in, short inlen, byte[] out) {
|
||||
if (in == null || out == null || inlen == 0) return;
|
||||
|
||||
// 处理缓冲区中剩余的非4字节数据
|
||||
if (this.buflen > 0) {
|
||||
int need = 4 - this.buflen;
|
||||
int copy = Math.min(inlen, need);
|
||||
short copy;
|
||||
if (inlen < need) {
|
||||
copy = (short) inlen;
|
||||
} else {
|
||||
copy = (short) need;
|
||||
}
|
||||
|
||||
System.arraycopy(in, 0, this.buf, this.buflen, copy);
|
||||
Util.arrayCopyNonAtomic(in, (short) 0, this.buf, (short) this.buflen, copy);
|
||||
this.buflen += copy;
|
||||
|
||||
// 调整输入指针和长度
|
||||
byte[] newIn = new byte[inlen - copy];
|
||||
if (inlen - copy > 0) {
|
||||
System.arraycopy(in, copy, newIn, 0, inlen - copy);
|
||||
Util.arrayCopyNonAtomic(in, copy, newIn, (short)0, (short) (inlen - copy));
|
||||
}
|
||||
in = newIn;
|
||||
inlen -= copy;
|
||||
@@ -65,12 +70,12 @@ public final class Zuc256EncryptCtx {
|
||||
putU32(out, 0, plain ^ keystream);
|
||||
|
||||
this.buflen = 0;
|
||||
Arrays.fill(this.buf, (byte) 0);
|
||||
Util.arrayFillNonAtomic(this.buf, (short) 0, (short) this.buf.length, (byte) 0);
|
||||
|
||||
// 调整输出指针
|
||||
byte[] newOut = new byte[out.length - 4];
|
||||
if (out.length - 4 > 0) {
|
||||
System.arraycopy(out, 4, newOut, 0, out.length - 4);
|
||||
Util.arrayCopyNonAtomic(out, (short)4, newOut, (short)0, (short)(out.length - 4));
|
||||
}
|
||||
out = newOut;
|
||||
}
|
||||
@@ -92,7 +97,7 @@ public final class Zuc256EncryptCtx {
|
||||
int processed = fullBlocks * 4;
|
||||
byte[] newIn = new byte[inlen - processed];
|
||||
if (inlen - processed > 0) {
|
||||
System.arraycopy(in, processed, newIn, 0, inlen - processed);
|
||||
Util.arrayCopyNonAtomic(in, (short) processed, newIn, (short) 0, (short) (inlen - processed));
|
||||
}
|
||||
in = newIn;
|
||||
inlen -= processed;
|
||||
@@ -100,7 +105,7 @@ public final class Zuc256EncryptCtx {
|
||||
|
||||
// 缓存剩余不足4字节的数据
|
||||
if (inlen > 0) {
|
||||
System.arraycopy(in, 0, this.buf, 0, inlen);
|
||||
Util.arrayCopyNonAtomic(in, (short) 0, this.buf, (short) 0, (short) inlen);
|
||||
this.buflen = inlen;
|
||||
}
|
||||
}
|
||||
@@ -122,9 +127,12 @@ public final class Zuc256EncryptCtx {
|
||||
}
|
||||
|
||||
// 清理上下文
|
||||
Arrays.fill(this.buf, (byte) 0);
|
||||
Util.arrayFillNonAtomic(this.buf, (short) 0, (short) this.buf.length, (byte) 0);
|
||||
this.buflen = 0;
|
||||
Arrays.fill(this.state.LFSR, 0);
|
||||
// 清零操作
|
||||
for (short i = 0; i < (short)this.state.LFSR.length; i++) {
|
||||
this.state.LFSR[i] = 0;
|
||||
}
|
||||
this.state.R1 = 0;
|
||||
this.state.R2 = 0;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.zuc.zuc256;
|
||||
|
||||
import javacard.framework.Util;
|
||||
|
||||
/**
|
||||
* 辅助工具:装载/存储、位运算、线性变换、打印等。
|
||||
*/
|
||||
@@ -77,7 +79,9 @@ public final class Zuc256Util {
|
||||
if (input25Byte == null || output23Byte == null) return;
|
||||
|
||||
// 复制前17字节
|
||||
System.arraycopy(input25Byte, 0, output23Byte, 0, 17);
|
||||
// System.arraycopy(input25Byte, 0, output23Byte, 0, 17);
|
||||
Util.arrayCopyNonAtomic(input25Byte, (short)0, output23Byte, (short)0, (short)17);
|
||||
|
||||
|
||||
// 处理剩余8字节
|
||||
byte[] src = new byte[8];
|
||||
@@ -94,11 +98,11 @@ public final class Zuc256Util {
|
||||
}
|
||||
|
||||
/** 打印十六进制(调试用,TODO 生产/JC 环境可移除) */
|
||||
public static void printHex(String label, byte[] data, int len) {
|
||||
System.out.print(label + ": ");
|
||||
for (int i = 0; i < len; i++) {
|
||||
System.out.printf("%02x ", data[i] & 0xFF);
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
// public static void printHex(String label, byte[] data, int len) {
|
||||
// System.out.print(label + ": ");
|
||||
// for (int i = 0; i < len; i++) {
|
||||
// System.out.printf("%02x ", data[i] & 0xFF);
|
||||
// }
|
||||
// System.out.println();
|
||||
// }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user