临时存储

This commit is contained in:
zcy
2025-09-05 14:36:09 +08:00
parent 5122f8eade
commit 69dd449aca
10 changed files with 210 additions and 84 deletions

View File

@@ -15,8 +15,8 @@ sourceSets {
/** 统一编译编码 */ /** 统一编译编码 */
tasks.withType(JavaCompile).configureEach { t -> tasks.withType(JavaCompile).configureEach { t ->
t.options.encoding = "UTF-8" t.options.encoding = "UTF-8"
t.sourceCompatibility = "1.5" t.sourceCompatibility = "1.8"
t.targetCompatibility = "1.5" t.targetCompatibility = "1.8"
def jcHome = System.getenv("JC_HOME") def jcHome = System.getenv("JC_HOME")
if (!jcHome) throw new GradleException("缺少 JC_HOME") if (!jcHome) throw new GradleException("缺少 JC_HOME")
t.options.bootstrapClasspath = files("${jcHome}/lib/api_classic.jar") t.options.bootstrapClasspath = files("${jcHome}/lib/api_classic.jar")
@@ -34,10 +34,12 @@ dependencies {
/** ===== 用本地 JCDK converter 生成 CAP ===== */ /** ===== 用本地 JCDK converter 生成 CAP ===== */
def pkgName = "com.zuc.zuc256" // ← 改成你的包名 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 packageAID = "0xA0:0x00:0x00:0x03:0x33:0x01:0x01" // ← 改成你的包 AID
def appletAID = "0xA0:0x00:0x00:0x03:0x33:0x01:0x01:0x01"// ← 改成你的实例 AID def appletAID = "0xA0:0x00:0x00:0x03:0x33:0x01:0x01:0x01"// ← 改成你的实例 AID
def ver = "1.0" def ver = "1.0"
tasks.register("buildCap") { tasks.register("buildCap") {
group = "build" group = "build"
description = "Generate CAP via JCDK converter.bat" description = "Generate CAP via JCDK converter.bat"
@@ -61,7 +63,7 @@ tasks.register("buildCap") {
if (!batFile.exists()) throw new GradleException("未找到 converter.bat${batFile}") if (!batFile.exists()) throw new GradleException("未找到 converter.bat${batFile}")
// 确认 .class 存在 // 确认 .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}") if (!cls.exists()) throw new GradleException("未找到已编译类:${cls}")
@@ -96,7 +98,7 @@ tasks.register("buildCap") {
if (result.exitValue != 0) { if (result.exitValue != 0) {
println "---- converter.log tail ----" 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}") throw new GradleException("converter 退出码:${result.exitValue}")
} else { } else {
println "CAP 生成成功,目录:${file("$buildDir/javacard").absolutePath}" println "CAP 生成成功,目录:${file("$buildDir/javacard").absolutePath}"
@@ -104,3 +106,5 @@ tasks.register("buildCap") {
} }
} }

3
gradle.properties Normal file
View File

@@ -0,0 +1,3 @@
# 统一 Gradle/JVM 的默认编码
org.gradle.jvmargs=-Xmx2g -Dfile.encoding=UTF-8
systemProp.file.encoding=UTF-8

View File

@@ -2,6 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.4-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.4-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
org.gradle.jvmargs=-Dfile.encoding=UTF-8
org.gradle.console=plain

View 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
}
}

View File

@@ -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);
}
}

View 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);
}
}
}

View File

@@ -63,7 +63,10 @@ public final class Zuc256Core {
a = (a & 0x7FFFFFFF) + (a >>> 31); a = (a & 0x7FFFFFFF) + (a >>> 31);
int v = (int) ((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; LFSR[15] = v;
state.R1 = R1; state.R1 = R1;
@@ -119,7 +122,10 @@ public final class Zuc256Core {
a = (a & 0x7FFFFFFF) + (a >>> 31); a = (a & 0x7FFFFFFF) + (a >>> 31);
int v = (int) ((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; LFSR[15] = v;
} }
@@ -171,7 +177,11 @@ public final class Zuc256Core {
a = (a & 0x7FFFFFFF) + (a >>> 31); a = (a & 0x7FFFFFFF) + (a >>> 31);
int v = (int) ((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; LFSR[15] = v;
state.R1 = R1; state.R1 = R1;
@@ -250,7 +260,10 @@ public final class Zuc256Core {
v = add31(v, rot31(LFSR[15], 15)); v = add31(v, rot31(LFSR[15], 15));
v = add31(v, W >>> 1); 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; LFSR[15] = v;
} }
@@ -284,7 +297,10 @@ public final class Zuc256Core {
a = (a & 0x7FFFFFFF) + (a >>> 31); a = (a & 0x7FFFFFFF) + (a >>> 31);
int v = (int) ((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; LFSR[15] = v;
key.R1 = R1; key.R1 = R1;

View File

@@ -1,9 +1,8 @@
package com.zuc.zuc256; package com.zuc.zuc256;
import java.util.Arrays;
import static com.zuc.zuc256.Zuc256Util.extractIv; 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 final class Zuc256Demo {
public static void main(String[] args) { public static void main(short args[]) {
// 1. 明文 // 1. 明文
byte[] plaintext = "ZUC256对称加解密测试:1234567890".getBytes(); byte[] plaintext = new byte[] {
int plaintextLen = plaintext.length; 0x5A, 0x55, 0x43, 0x32, 0x35, 0x36,
System.out.println("明文: " + new String(plaintext)); (byte)0xE5,(byte)0xAF,(byte)0xB9,(byte)0xE7,(byte)0xA7,(byte)0xB0,
printHex("明文(十六进制)", plaintext, plaintextLen); (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) // 2. 密钥(32字节ASCII)
byte[] key = "0123456789abcdef0123456789abcdef".getBytes(); byte[] key = new byte[] {
printHex("密钥", key, 32); 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) // 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]; byte[] iv = new byte[23];
extractIv(inputIv25Byte, iv); extractIv(inputIv25Byte, iv);
printHex("提取后的IV", iv, 23); // printHex("提取后的IV", iv, 23);
// 4. 分配加密/解密缓冲区 // 4. 分配加密/解密缓冲区
byte[] ciphertext = new byte[plaintextLen]; byte[] ciphertext = new byte[plaintextLen];
@@ -37,25 +59,25 @@ public final class Zuc256Demo {
Zuc256State stateEnc = new Zuc256State(); Zuc256State stateEnc = new Zuc256State();
Zuc256Core.initState(stateEnc, key, iv); Zuc256Core.initState(stateEnc, key, iv);
zuc256Crypt(stateEnc, plaintext, plaintextLen, ciphertext); zuc256Crypt(stateEnc, plaintext, plaintextLen, ciphertext);
printHex("密文", ciphertext, plaintextLen); // printHex("密文", ciphertext, plaintextLen);
// 6. 解密(重新初始化状态) // 6. 解密(重新初始化状态)
Zuc256State stateDec = new Zuc256State(); Zuc256State stateDec = new Zuc256State();
Zuc256Core.initState(stateDec, key, iv); Zuc256Core.initState(stateDec, key, iv);
zuc256Crypt(stateDec, ciphertext, plaintextLen, decryptedtext); zuc256Crypt(stateDec, ciphertext, plaintextLen, decryptedtext);
printHex("解密后", decryptedtext, plaintextLen); // printHex("解密后", decryptedtext, plaintextLen);
System.out.println("解密文本: " + new String(decryptedtext)); // System.out.println("解密文本: " + new String(decryptedtext));
// 7. 验证结果 // 7. 验证结果
if (Arrays.equals(plaintext, decryptedtext)) { // if (Arrays.equals(plaintext, decryptedtext)) {
System.out.println("=== 测试成功: 解密结果与明文一致 ==="); // System.out.println("=== 测试成功: 解密结果与明文一致 ===");
} else { // } else {
System.out.println("=== 测试失败: 解密结果与明文不一致 ==="); // 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; if (state == null || in == null || out == null) return;
Zuc256EncryptCtx ctx = new Zuc256EncryptCtx(state); Zuc256EncryptCtx ctx = new Zuc256EncryptCtx(state);
@@ -68,6 +90,6 @@ public final class Zuc256Demo {
System.arraycopy(out, remainingOffset, finishOut, 0, finishOut.length); System.arraycopy(out, remainingOffset, finishOut, 0, finishOut.length);
} }
ctx.finish(finishOut); ctx.finish(finishOut);
System.arraycopy(finishOut, 0, out, remainingOffset, finishOut.length); System.arraycopy(finishOut, (short)0, out, (short)remainingOffset, (short)finishOut.length);
} }
} }

View File

@@ -1,6 +1,6 @@
package com.zuc.zuc256; 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.zuc256GenerateKeystream;
import static com.zuc.zuc256.Zuc256Core.zuc256GenerateKeyword; import static com.zuc.zuc256.Zuc256Core.zuc256GenerateKeyword;
@@ -33,27 +33,32 @@ public final class Zuc256EncryptCtx {
// 初始化加密上下文 // 初始化加密上下文
public void init(byte[] key32, byte[] iv) { 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; this.buflen = 0;
Zuc256Core.initState(this.state, key32, iv); 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; if (in == null || out == null || inlen == 0) return;
// 处理缓冲区中剩余的非4字节数据 // 处理缓冲区中剩余的非4字节数据
if (this.buflen > 0) { if (this.buflen > 0) {
int need = 4 - this.buflen; 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; this.buflen += copy;
// 调整输入指针和长度 // 调整输入指针和长度
byte[] newIn = new byte[inlen - copy]; byte[] newIn = new byte[inlen - copy];
if (inlen - copy > 0) { if (inlen - copy > 0) {
System.arraycopy(in, copy, newIn, 0, inlen - copy); Util.arrayCopyNonAtomic(in, copy, newIn, (short)0, (short) (inlen - copy));
} }
in = newIn; in = newIn;
inlen -= copy; inlen -= copy;
@@ -65,12 +70,12 @@ public final class Zuc256EncryptCtx {
putU32(out, 0, plain ^ keystream); putU32(out, 0, plain ^ keystream);
this.buflen = 0; 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]; byte[] newOut = new byte[out.length - 4];
if (out.length - 4 > 0) { 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; out = newOut;
} }
@@ -92,7 +97,7 @@ public final class Zuc256EncryptCtx {
int processed = fullBlocks * 4; int processed = fullBlocks * 4;
byte[] newIn = new byte[inlen - processed]; byte[] newIn = new byte[inlen - processed];
if (inlen - processed > 0) { 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; in = newIn;
inlen -= processed; inlen -= processed;
@@ -100,7 +105,7 @@ public final class Zuc256EncryptCtx {
// 缓存剩余不足4字节的数据 // 缓存剩余不足4字节的数据
if (inlen > 0) { 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; 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; 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.R1 = 0;
this.state.R2 = 0; this.state.R2 = 0;
} }

View File

@@ -1,5 +1,7 @@
package com.zuc.zuc256; package com.zuc.zuc256;
import javacard.framework.Util;
/** /**
* 辅助工具:装载/存储、位运算、线性变换、打印等。 * 辅助工具:装载/存储、位运算、线性变换、打印等。
*/ */
@@ -77,7 +79,9 @@ public final class Zuc256Util {
if (input25Byte == null || output23Byte == null) return; if (input25Byte == null || output23Byte == null) return;
// 复制前17字节 // 复制前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字节 // 处理剩余8字节
byte[] src = new byte[8]; byte[] src = new byte[8];
@@ -94,11 +98,11 @@ public final class Zuc256Util {
} }
/** 打印十六进制调试用TODO 生产/JC 环境可移除) */ /** 打印十六进制调试用TODO 生产/JC 环境可移除) */
public static void printHex(String label, byte[] data, int len) { // public static void printHex(String label, byte[] data, int len) {
System.out.print(label + ": "); // System.out.print(label + ": ");
for (int i = 0; i < len; i++) { // for (int i = 0; i < len; i++) {
System.out.printf("%02x ", data[i] & 0xFF); // System.out.printf("%02x ", data[i] & 0xFF);
} // }
System.out.println(); // System.out.println();
} // }
} }