莫名奇妙的验签成功

This commit is contained in:
cheney 2026-05-22 10:57:29 +08:00
parent 72eff5f4a4
commit 5a2c94a32c

View File

@ -314,6 +314,11 @@ public class CMSUtil {
System.out.println("\n 处理第 " + (si+1) + " 个 SignerInfo...");
ASN1Encodable signerInfoEncodable = signerInfosSet.getObjectAt(si);
ASN1Primitive signerInfoPrim = signerInfoEncodable.toASN1Primitive();
byte[] signerInfoDer = signerInfoPrim.getEncoded(ASN1Encoding.DER);
System.out.println(" SignerInfo DER 编码长度: " + signerInfoDer.length + " bytes");
System.out.println(" SignerInfo DER 编码: " + bytesToHex(signerInfoDer));
System.out.println(" SignerInfo 原始类型: " + signerInfoPrim.getClass().getSimpleName());
String signerInfoPrimClassName = signerInfoPrim.getClass().getName();
@ -487,40 +492,31 @@ public class CMSUtil {
System.out.println(" 签名值 (Hex): " + bytesToHex(signatureValue));
System.out.println(" signedAttrs 数据类型: " + authAttrsData.getClass().getName());
String[] algNames = {"SM3withSM2", "SHA256withSM2", "SM2"};
byte[] signingData = signedAttrsEncoded;
boolean valid = false;
for (String algName : algNames) {
try {
Signature signature = Signature.getInstance(algName, "BC");
signature.initVerify(signerCert.getPublicKey());
signature.update(signedAttrsEncoded);
valid = signature.verify(signatureValue);
System.out.println(" 算法 " + algName + " 验签结果: " + (valid ? "成功" : "失败"));
if (valid) break;
} catch (Exception e) {
System.out.println(" 算法 " + algName + " 失败: " + e.getMessage());
}
}
if (!valid) {
System.out.println("\n [调试] 尝试使用原始签名值格式验签...");
try {
Signature signature = Signature.getInstance("SM3withSM2", "BC");
signature.initVerify(signerCert.getPublicKey());
signature.update(signedAttrsEncoded);
byte[] rawSig = new byte[64];
if (signatureValue.length >= 65 && signatureValue[0] == 0x30) {
int offset = signatureValue[1] >= 0x81 ? (signatureValue[1] == 0x81 ? 3 : 2) : 2;
if (signatureValue.length >= offset + 32 + 2) {
System.arraycopy(signatureValue, offset + 1, rawSig, 0, 32);
System.arraycopy(signatureValue, offset + 33, rawSig, 32, 32);
valid = signature.verify(rawSig);
System.out.println(" 原始格式验签结果: " + (valid ? "成功" : "失败"));
}
}
} catch (Exception e) {
System.out.println(" 原始格式验签失败: " + e.getMessage());
if (authAttrsData instanceof ASN1TaggedObject) {
System.out.println(" [GMT 0010-2012] 尝试使用两种方式验签:");
System.out.println("\n 方式1: 使用带标签的完整编码 (包含 [0] IMPLICIT 标签)");
valid = verifySM2Signature(signerCert.getPublicKey(), signingData, signatureValue);
if (!valid) {
System.out.println("\n 方式2: 使用标签内的原始数据 (不包含标签)");
ASN1TaggedObject tagged = (ASN1TaggedObject) authAttrsData;
ASN1Primitive inner = tagged.getObject();
byte[] innerEncoded = inner.getEncoded(ASN1Encoding.DER);
System.out.println(" 内部数据长度: " + innerEncoded.length + " bytes");
System.out.println(" 内部数据 Hex: " + bytesToHex(innerEncoded));
valid = verifySM2Signature(signerCert.getPublicKey(), innerEncoded, signatureValue);
}
} else {
valid = verifySM2Signature(signerCert.getPublicKey(), signingData, signatureValue);
}
if (!valid) {
System.out.println("\n [调试] 尝试调整签名值格式...");
valid = tryAlternativeFormats(signerCert.getPublicKey(), signingData, signatureValue);
}
return new SignedAndEnvelopedVerifyResult(valid, messageDigest, signerCert,
@ -693,6 +689,89 @@ public class CMSUtil {
throw new Exception("未找到有效的签名信息");
}
private static boolean verifySM2Signature(PublicKey publicKey, byte[] data, byte[] signature) {
try {
Signature sig = Signature.getInstance("SM3withSM2", "BC");
sig.initVerify(publicKey);
sig.update(data);
boolean result = sig.verify(signature);
System.out.println(" 验签结果: " + (result ? "成功" : "失败"));
if (!result && data.length > 0 && data[0] == 0x30) {
System.out.println(" [GMT 0010-2012] 尝试将SEQUENCE转换为SET...");
byte[] setData = convertSequenceToSet(data);
if (setData != null) {
sig = Signature.getInstance("SM3withSM2", "BC");
sig.initVerify(publicKey);
sig.update(setData);
result = sig.verify(signature);
System.out.println(" SET格式验签结果: " + (result ? "成功" : "失败"));
}
}
return result;
} catch (Exception e) {
System.out.println(" 验签失败: " + e.getMessage());
return false;
}
}
private static byte[] convertSequenceToSet(byte[] sequenceData) {
try {
if (sequenceData.length < 2 || sequenceData[0] != 0x30) {
return null;
}
byte[] setData = new byte[sequenceData.length];
System.arraycopy(sequenceData, 0, setData, 0, sequenceData.length);
setData[0] = 0x31;
return setData;
} catch (Exception e) {
return null;
}
}
private static boolean tryAlternativeFormats(PublicKey publicKey, byte[] data, byte[] signature) {
try {
if (signature.length >= 65 && signature[0] == 0x30) {
System.out.println(" 尝试解析 ASN.1 编码的签名值...");
int offset = 2;
if (signature[1] >= 0x81) {
offset = signature[1] == 0x81 ? 3 : 2 + (signature[1] & 0xFF);
}
if (signature[offset] == 0x02) {
int rLen = signature[offset + 1];
byte[] r = new byte[rLen];
System.arraycopy(signature, offset + 2, r, 0, rLen);
offset += 2 + rLen;
if (signature[offset] == 0x02) {
int sLen = signature[offset + 1];
byte[] s = new byte[sLen];
System.arraycopy(signature, offset + 2, s, 0, sLen);
byte[] rawSig = new byte[64];
int rStart = r[0] == 0x00 ? 1 : 0;
int sStart = s[0] == 0x00 ? 1 : 0;
System.arraycopy(r, rStart, rawSig, 32 - r.length + rStart, r.length - rStart);
System.arraycopy(s, sStart, rawSig, 64 - s.length + sStart, s.length - sStart);
Signature sig = Signature.getInstance("SM3withSM2", "BC");
sig.initVerify(publicKey);
sig.update(data);
boolean result = sig.verify(rawSig);
System.out.println(" 原始格式(R+S)验签结果: " + (result ? "成功" : "失败"));
return result;
}
}
}
} catch (Exception e) {
System.out.println(" 尝试其他格式失败: " + e.getMessage());
}
return false;
}
public static void main(String[] args) {
if (args.length < 1) {
System.out.println("用法: java CMSUtil <base64_cms_data>");