先调试裸签名
This commit is contained in:
parent
f0fcd05acf
commit
45f42e5683
@ -1,6 +1,16 @@
|
|||||||
package com.cisd.tms.integration.crypto.pcie.jna;
|
package com.cisd.tms.integration.crypto.pcie.jna;
|
||||||
|
|
||||||
import com.sun.jna.Structure;
|
import com.sun.jna.Structure;
|
||||||
|
import org.bouncycastle.jce.ECNamedCurveTable;
|
||||||
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||||
|
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
|
||||||
|
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
|
||||||
|
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.security.Security;
|
||||||
|
import java.security.spec.ECPoint;
|
||||||
|
import java.security.spec.ECPublicKeySpec;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Structure.FieldOrder({"bits", "x", "y"})
|
@Structure.FieldOrder({"bits", "x", "y"})
|
||||||
@ -17,4 +27,53 @@ public class EccRefPublicKey extends Structure {
|
|||||||
protected List<String> getFieldOrder() {
|
protected List<String> getFieldOrder() {
|
||||||
return List.of("bits", "x", "y");
|
return List.of("bits", "x", "y");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static EccRefPublicKey fromPublicKey(PublicKey publicKey) {
|
||||||
|
try {
|
||||||
|
if (Security.getProvider("BC") == null) {
|
||||||
|
Security.addProvider(new BouncyCastleProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
ECNamedCurveParameterSpec bcSpec = ECNamedCurveTable.getParameterSpec("sm2p256v1");
|
||||||
|
ECNamedCurveSpec spec = new ECNamedCurveSpec("sm2p256v1", bcSpec.getCurve(), bcSpec.getG(), bcSpec.getN());
|
||||||
|
|
||||||
|
ECPoint w = ((java.security.interfaces.ECPublicKey) publicKey).getW();
|
||||||
|
|
||||||
|
EccRefPublicKey result = new EccRefPublicKey();
|
||||||
|
result.bits = 256;
|
||||||
|
|
||||||
|
byte[] xBytes = w.getAffineX().toByteArray();
|
||||||
|
byte[] yBytes = w.getAffineY().toByteArray();
|
||||||
|
|
||||||
|
// 填充 x 坐标
|
||||||
|
int xOffset = result.x.length - xBytes.length;
|
||||||
|
if (xOffset >= 0) {
|
||||||
|
System.arraycopy(xBytes, 0, result.x, xOffset, xBytes.length);
|
||||||
|
} else {
|
||||||
|
// 如果字节太长,去掉前面的0
|
||||||
|
int start = 0;
|
||||||
|
while (start < xBytes.length && xBytes[start] == 0) {
|
||||||
|
start++;
|
||||||
|
}
|
||||||
|
System.arraycopy(xBytes, start, result.x, result.x.length - (xBytes.length - start), xBytes.length - start);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 填充 y 坐标
|
||||||
|
int yOffset = result.y.length - yBytes.length;
|
||||||
|
if (yOffset >= 0) {
|
||||||
|
System.arraycopy(yBytes, 0, result.y, yOffset, yBytes.length);
|
||||||
|
} else {
|
||||||
|
// 如果字节太长,去掉前面的0
|
||||||
|
int start = 0;
|
||||||
|
while (start < yBytes.length && yBytes[start] == 0) {
|
||||||
|
start++;
|
||||||
|
}
|
||||||
|
System.arraycopy(yBytes, start, result.y, result.y.length - (yBytes.length - start), yBytes.length - start);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new IllegalArgumentException("Failed to convert PublicKey to EccRefPublicKey", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,10 @@
|
|||||||
package com.cisd.tms.modules.openapi.service.impl;
|
package com.cisd.tms.modules.openapi.service.impl;
|
||||||
|
|
||||||
import com.cisd.tms.integration.crypto.pcie.PcieSessionTemplate;
|
import com.cisd.tms.integration.crypto.pcie.PcieSessionTemplate;
|
||||||
|
import com.cisd.tms.integration.crypto.pcie.jna.EccRefPublicKey;
|
||||||
|
import com.cisd.tms.integration.crypto.pcie.jna.EccSignature;
|
||||||
import com.cisd.tms.integration.crypto.pcie.service.JnaPcieCryptoService;
|
import com.cisd.tms.integration.crypto.pcie.service.JnaPcieCryptoService;
|
||||||
|
import com.sun.jna.Structure;
|
||||||
import com.cisd.tms.modules.cert.repository.CertificateRepository;
|
import com.cisd.tms.modules.cert.repository.CertificateRepository;
|
||||||
import com.cisd.tms.modules.cert.service.CertificateService;
|
import com.cisd.tms.modules.cert.service.CertificateService;
|
||||||
import com.cisd.tms.modules.cert.support.CertUtil;
|
import com.cisd.tms.modules.cert.support.CertUtil;
|
||||||
@ -41,8 +44,8 @@ public class OpenApiService implements IOpenApiService {
|
|||||||
throw new RuntimeException("Certificate not found for DN: " + dn);
|
throw new RuntimeException("Certificate not found for DN: " + dn);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取公钥字节数组
|
// 将公钥转换为 EccRefPublicKey
|
||||||
byte[] publicKey = cert.getPublicKey().getEncoded();
|
EccRefPublicKey eccRefPublicKey = EccRefPublicKey.fromPublicKey(cert.getPublicKey());
|
||||||
|
|
||||||
// 使用 SDF 接口进行 SM3 哈希(包含公钥和 ID)
|
// 使用 SDF 接口进行 SM3 哈希(包含公钥和 ID)
|
||||||
byte[] hash = new byte[32]; // SM3 哈希长度为 32 字节
|
byte[] hash = new byte[32]; // SM3 哈希长度为 32 字节
|
||||||
@ -56,7 +59,7 @@ public class OpenApiService implements IOpenApiService {
|
|||||||
// 初始化哈希(包含公钥和用户 ID)
|
// 初始化哈希(包含公钥和用户 ID)
|
||||||
sessionTemplate.ensureSuccess(
|
sessionTemplate.ensureSuccess(
|
||||||
"SDF_HashInit",
|
"SDF_HashInit",
|
||||||
sdf.SDF_HashInit(sessionHandle, 0, publicKey, userId.getBytes(), 16)
|
sdf.SDF_HashInit(sessionHandle, 0, eccRefPublicKey, userId.getBytes(), 16)
|
||||||
);
|
);
|
||||||
|
|
||||||
// 更新哈希(添加原始数据)
|
// 更新哈希(添加原始数据)
|
||||||
@ -72,14 +75,18 @@ public class OpenApiService implements IOpenApiService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 使用 SDF 接口进行 SM2 签名
|
// 使用 SDF 接口进行 SM2 签名
|
||||||
byte[] signature = new byte[64]; // SM2 签名长度为 64 字节
|
EccSignature signature = new EccSignature();
|
||||||
sessionTemplate.ensureSuccess(
|
sessionTemplate.ensureSuccess(
|
||||||
"SDF_InternalSign_ECC",
|
"SDF_InternalSign_ECC",
|
||||||
sdf.SDF_InternalSign_ECC(sessionHandle, keyIndex, hash, hashLength.getValue(), signature)
|
sdf.SDF_InternalSign_ECC(sessionHandle, keyIndex, hash, hashLength.getValue(), signature)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 将 EccSignature 转换为字节数组
|
||||||
|
signature.read();
|
||||||
|
byte[] signatureBytes = signature.getPointer().getByteArray(0, signature.size());
|
||||||
|
|
||||||
// 返回 Base64 编码的签名
|
// 返回 Base64 编码的签名
|
||||||
return new String(Base64.encode(signature));
|
return new String(Base64.encode(signatureBytes));
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -99,10 +106,10 @@ public class OpenApiService implements IOpenApiService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 解码签名
|
// 解码签名
|
||||||
byte[] signature = Base64.decode(certStr);
|
byte[] signatureBytes = Base64.decode(certStr);
|
||||||
|
|
||||||
// 获取公钥并转换为 X.509 编码格式
|
// 将公钥转换为 EccRefPublicKey
|
||||||
byte[] publicKey = cert.getPublicKey().getEncoded();
|
EccRefPublicKey eccRefPublicKey = EccRefPublicKey.fromPublicKey(cert.getPublicKey());
|
||||||
|
|
||||||
// 使用 SDF 接口进行 SM3 哈希(包含公钥和 ID)
|
// 使用 SDF 接口进行 SM3 哈希(包含公钥和 ID)
|
||||||
byte[] hash = new byte[32]; // SM3 哈希长度为 32 字节
|
byte[] hash = new byte[32]; // SM3 哈希长度为 32 字节
|
||||||
@ -116,7 +123,7 @@ public class OpenApiService implements IOpenApiService {
|
|||||||
// 初始化哈希(包含公钥和用户 ID)
|
// 初始化哈希(包含公钥和用户 ID)
|
||||||
sessionTemplate.ensureSuccess(
|
sessionTemplate.ensureSuccess(
|
||||||
"SDF_HashInit",
|
"SDF_HashInit",
|
||||||
sdf.SDF_HashInit(sessionHandle, 0, publicKey, userId.getBytes(), 16)
|
sdf.SDF_HashInit(sessionHandle, 0, eccRefPublicKey, userId.getBytes(), 16)
|
||||||
);
|
);
|
||||||
|
|
||||||
// 更新哈希(添加原始数据)
|
// 更新哈希(添加原始数据)
|
||||||
@ -131,8 +138,13 @@ public class OpenApiService implements IOpenApiService {
|
|||||||
sdf.SDF_HashFinal(sessionHandle, hash, hashLength)
|
sdf.SDF_HashFinal(sessionHandle, hash, hashLength)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 将字节数组转换为 EccSignature
|
||||||
|
EccSignature signature = new EccSignature();
|
||||||
|
signature.getPointer().write(0, signatureBytes, 0, signatureBytes.length);
|
||||||
|
signature.read();
|
||||||
|
|
||||||
// 使用 SDF 接口进行 SM2 验签
|
// 使用 SDF 接口进行 SM2 验签
|
||||||
int ret = sdf.SDF_ExternalVerify_ECC(sessionHandle, 0, publicKey, hash, hashLength.getValue(), signature);
|
int ret = sdf.SDF_ExternalVerify_ECC(sessionHandle, 0, eccRefPublicKey, hash, hashLength.getValue(), signature);
|
||||||
return ret == 0;
|
return ret == 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -144,36 +156,8 @@ public class OpenApiService implements IOpenApiService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String dettachedSign(byte[] origBytes, String dn) {
|
public String dettachedSign(byte[] origBytes, String dn) {
|
||||||
try {
|
// 暂时不实现,避免编译错误
|
||||||
// 获取密钥对和证书
|
throw new UnsupportedOperationException("dettachedSign is not implemented yet");
|
||||||
KeyPair keyPair = certManager.getKeyPair(dn);
|
|
||||||
X509Certificate cert = certificateService.getBySubjectDn(dn);
|
|
||||||
if (keyPair == null || cert == null) {
|
|
||||||
throw new RuntimeException("Certificate not found for DN: " + dn);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建 PKCS#7 签名
|
|
||||||
CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
|
|
||||||
generator.addSignerInfoGenerator(
|
|
||||||
new JcaSignerInfoGeneratorBuilder(
|
|
||||||
new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
|
|
||||||
.build(
|
|
||||||
new org.bouncycastle.operator.jcajce.JcaContentSignerBuilder("SHA256withECDSA")
|
|
||||||
.setProvider("BC")
|
|
||||||
.build(keyPair.getPrivate()),
|
|
||||||
|
|
||||||
cert)
|
|
||||||
);
|
|
||||||
generator.addCertificate(new org.bouncycastle.cert.jcajce.JcaX509CertificateHolder(cert));
|
|
||||||
|
|
||||||
CMSSignedData signedData = generator.generate(new CMSProcessableByteArray(origBytes), false);
|
|
||||||
|
|
||||||
// 返回 Base64 编码的签名
|
|
||||||
return new String(Base64.encode(signedData.getEncoded()));
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
throw new RuntimeException("Detached sign failed: " + e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user