java - 生成的数字签名 Java 不会在 openssl 中验证
问题描述
我正在用 Java 签署一个二进制文件。我能够在 Java 代码中签名和验证,但是在 openssl 中使用生成的签名时,它无法验证相同的二进制文件。步骤是:加载数据 -> 创建 SHA256 哈希 -> 签名哈希
这应该等同于在 openssl 中执行此操作: openssl dgst -sha256 -sign private.key -binary target.bin > signature.bin verify: openssl dgst -sha256 -verify public.key -signature signature.bin
我验证了 sha256 与从 openssl 生成的匹配。
public class Main {
public static void main(final String[] args) {
Signature signer;
KeyStore ks;
byte[] signature;
PrivateKey privateKey;
PublicKey publicKey;
String alias = "ctest3";
String sigfile = "c:\\temp\\signature";
String datafile = "c:\\temp\\data.bin";
try {
ks = KeyStore.getInstance("ncipher.sworld", "nCipherKM");
FileInputStream in = new FileInputStream("C:\\private\\ctest3.ncsw");
ks.load(in, null);
} catch (KeyStoreException |
NoSuchAlgorithmException |
CertificateException |
IOException |
NoSuchProviderException e) {
System.err.println(e.getMessage());
return;
}
try {
privateKey = (PrivateKey) ks.getKey(alias, null);
Certificate cert = ks.getCertificate(alias);
publicKey = cert.getPublicKey();
} catch (Exception e) {
System.out.println(e.getMessage());
return;
}
byte[] payload;
try {
payload = Files.readAllBytes(Paths.get(datafile));
} catch (IOException e) {
System.out.println(e.getMessage());
return;
}
byte[] spayload = sha256(payload, false);
if (spayload == null) {
return;
}
try {
signer = Signature.getInstance("SHA256withECDSA");
signer.initSign(privateKey);
signer.update(spayload);
signature = signer.sign();
} catch (NoSuchAlgorithmException | SecurityException | SignatureException | InvalidKeyException e) {
System.out.println(e.getMessage());
return;
}
writeBytesToFile(signature, sigfile);
KeyPair kp = new KeyPair(publicKey, privateKey);
if (Verify(datafile, sigfile, kp)) {
System.out.println("success");
}
}
private static byte[] sha256(byte[] data) {
MessageDigest digest;
try {
digest = MessageDigest.getInstance("SHA-256");
byte[] mDigest = digest.digest(data);
return mDigest;
} catch (NoSuchAlgorithmException e) {
return null;
}
}
private static boolean Verify(String filename, String signaturePath, KeyPair kp) {
Signature verify;
byte[] dataRaw;
byte[] signature;
byte[] data;
try {
dataRaw = Files.readAllBytes(Paths.get(filename));
signature = Files.readAllBytes(Paths.get(signaturePath));
} catch (IOException e) {
System.out.println(e.getMessage());
return false;
}
data = sha256(dataRaw, false);
if (data == null)
return false;
try {
verify = Signature.getInstance("SHA256withECDSA");
PublicKey pub = kp.getPublic();
verify.initVerify(pub);
verify.update(data);
if (verify.verify(signature))
return true;
} catch (NoSuchAlgorithmException | SecurityException | SignatureException | InvalidKeyException e) {
System.out.println(e.getMessage());
return false;
}
return false;
}
private static void writeBytesToFile(byte[] bFile, String fileDest) {
try (FileOutputStream fileOuputStream = new FileOutputStream(fileDest)) {
fileOuputStream.write(bFile);
} catch (IOException e) {
e.printStackTrace();
}
}
}
解决方案
结果表明,当使用 SHA256withECDSA 密钥启动 Signature 对象时,它本身将在 sign() 调用期间生成 SHA256 哈希。在上面的代码中删除对“sha256()”的调用将使用 OpenSSL 进行验证。
推荐阅读
- java - 单击选项卡时,我想显示两个片段
- powershell - 审核远程服务器上的本地用户帐户
- oracle - 您如何分析触发器在 OracleDB 中需要多长时间?
- python - 从输入中找到平均值
- swiftui - 如何将自定义的 InfoWindow 添加到 google-maps swift ui 中的标记?
- ios - iOS中需要RSA公钥/私钥SecRefKey吗?
- python - 如何在字符串列表上使用循环并使用这些值访问字典中的嵌套值?
- javascript - 如何使用 javascript 将交易发送到 solana 中的链上程序?
- google-apps-script - 自动反转对谷歌工作表单元格的编辑
- javascript - VUE.JS - 如何在加载静态图像时提高性能