[英]How to verify signatureBytes after signing it with SHA256withRSA?
我正在使用“ Windows-MY” KeyStore簽名一些文本。 我想使用我的私鑰簽名並使用公鑰進行驗證。
KeyStore keyStore = KeyStore.getInstance("Windows-MY");
keyStore.load(null, null);
Enumeration en = keyStore.aliases();
while (en.hasMoreElements()) {
KeyStore keyStore = KeyStore.getInstance("Windows-MY");
keyStore.load(null, null);
String alias = en.nextElement().toString();
X509Certificate c = (X509Certificate) keyStore.getCertificate(alias);
String serialNumber = c.getSerialNumber().toString();
System.out.println("--" + aliasName);
PrivateKey privateKey = (PrivateKey) keyStore.getKey(aliasName, null);
PublicKey publicKey = (PublicKey) c.getPublicKey();
Certificate[] chain = keyStore.getCertificateChain(aliasName);
DataOutputStream fout = new DataOutputStream(outstream);
// -------------------------------------------------------
String data = "Monika";
byte[] content = data.getBytes();
Provider p = keyStore.getProvider();
// ----------------------signature---start---------------------------
Signature signature = Signature.getInstance("SHA256withRSA", p);
System.out.println(" signature.getProvider():"+ signature.getProvider());
signature.initSign(privateKey);
signature.update(content);
byte[] signatureBytes = signature.sign();
System.out.println("signatureBytes-------------"+ signatureBytes.toString());
// ----------------------signature----------end------------------
// ------------------------verification---------------
Signature signature1 = Signature.getInstance("SHA256withRSA", p);
System.out.println(" signature1.getProvider():"+ signature1.getProvider());
signature1.initVerify(publicKey);
signature1.update(content);
boolean verifies = signature1.verify(signatureBytes);
System.out.println("signature verifies: " + verifies);
// ------------------------------------------------
fout.close();
} // while
輸出:
privateKey:RSAPrivateKey [size=2048 bits, type=Exchange, container=AC0BEBA9-A361-4611-96D9-B365B671FBC3]
signature.getProvider():SunMSCAPI version 1.6
signatureBytes-------------[B@1402d5a
signature1.getProvider():SunRsaSign version 1.5
signature verifies: false
您的代碼有幾個問題:
您只是在使用Windows密鑰庫中的第一個證書/公鑰。 這實際上可能是正確的,但是密鑰庫中可能有多個證書,這只是您用於驗證的證書的巧合。
String alias = en.nextElement().toString(); X509Certificate c = (X509Certificate) keyStore.getCertificate(alias); PublicKey publicKey = c.getPublicKey(); PrivateKey privateKey = (PrivateKey) keyStore.getKey(DSCName, null);
您應該改寫keyStore.getCertificate(DSCName)
來確保它與私鑰匹配。
您正在無緣無故地生成密鑰(或者嘗試轉換現有密鑰)。 您可以完全刪除此代碼。 這也可以解決NullPointerException的問題:
byte[] encodedPrivateKey = privateKey.getEncoded(); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedPrivateKey); RSAPrivateKey privateKey1 = (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
您的問題中有很多不必要的代碼,例如加載證書鏈,但從不使用它。 這使其更難修復。 一個最小的(有效的)示例如下所示:
String alias = "myAlias"; String myData = "data to encrypt"; KeyStore keyStore = KeyStore.getInstance("Windows-MY"); keyStore.load(null, null); X509Certificate cert = (X509Certificate) keyStore.getCertificate(alias); PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, null); PublicKey publicKey = cert.getPublicKey(); Signature instance = Signature.getInstance("SHA256withRSA"); instance.initSign(privateKey, new SecureRandom()); instance.update(myData.getBytes("UTF-8")); byte[] signedBytes = instance.sign(); instance.initVerify(publicKey); instance.update(myData.getBytes("UTF-8")); System.out.println(instance.verify(signedBytes));
你在這里null
了
byte[] encodedPrivateKey = privateKey.getEncoded(); // are you sure that this byte array is not null ?
為了使事情更安全,請在此處檢查:
PrivateKey privateKey = (PrivateKey) keyStore.getKey(
DSCName, null); // this maybe returning null
因此,在出現錯誤的行之前,請進行檢查:
if(encodedPrivateKey==null){
System.out.println("private key is null");
}
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(
encodedPrivateKey);
Signature signature = Signature.getInstance("SHA256withRSA",p);
System.out.println(" signature.getProvider():"+ signature.getProvider());
signature.initSign(privateKey, new SecureRandom());
signature.update(byteData);
byte[] signatureBytes = signature.sign();
// X509Certificate cert1 =signatureBytes.
System.out.println("signatureBytes-------------"+ signatureBytes.toString());
// ----------------------signature----------end------------------
// ------------------------verification---------------
Signature signature1 = Signature.getInstance("SHA256withRSA");
System.out.println(" signature1.getProvider():"+ signature1.getProvider());
signature1.initVerify(publicKey);
signature1.update(byteData);
boolean verifies = signature1.verify(signatureBytes);
System.out.println("signature verifies: " + verifies);
使用摘要SHA256和RSA對某些文本/數據簽名后,請檢查此完整且有效的代碼以驗證簽名 :
/* verifyRSAsha256.java */
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.X509EncodedKeySpec;
import javax.xml.bind.DatatypeConverter;
/*
Compile:
clear && javac verifyRSAsha256.java && java verifyRSAsha256
Create private key:
openssl genrsa -des3 -out encrypted.pem 2048 && openssl rsa -in encrypted.pem -out private.pem -outform PEM && openssl rsa -in private.pem -pubout > public.pem
Create signature:
/bin/echo -n "some text that you want to be trusted" > data.txt
openssl dgst -sha256 -sign private.pem data.txt > signature.tmp
base64 signature.tmp
Verify signature:
openssl dgst -sha256 -verify public.pem -signature signature.tmp data.txt
*/
public class verifyRSAsha256 {
public static void main(String args[]){
String publicKey =
// "-----BEGIN PUBLIC KEY-----"+
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwns0JWYgEshlpLYsZQFc"+
"d5iVSqIHDO0zISLlO1aK4bbbosSvRE81+inKrG5mlnkIrv0+mJ/qTLY1RdBAVAe4"+
"GPLTpHmLJhEtq7stydm2cCTEPRwfJNjoHqATDHEm1KLVGA8k0hztfMr8fLChE3/K"+
"n2MHxzs7qhMLyBdPqbVC9RNja3i+Nl814xPTSXJ50zdJMLC56VtIU0xjqNjXN8iQ"+
"pLZ2EfcP55nZ/venD01yxfsUn4sQLFTAlXqygA10fdDv9y0eZvgaGGSb4MuPT7yD"+
"BfgNEU3tl4nRdSzPNkCkCmkuaa/pqZ5uw+G0HBwaQlHDwsnIcwE/xo6aHpt4xF4W"+
"/QIDAQAB";
// "-----END PUBLIC KEY-----";
byte[] signature, data;
// the signature is a binary data and I encoded it with base64, so the signature must be decoded from base64 to binary again
signature = DatatypeConverter.parseBase64Binary("Yy9CdQDfdYWwZkSu2SZgoFABHk5Bd3tzYvX73QR+GDCWpUsWrO5CXRF+j3dBz+bq1SRQ+1c1hdez5mMeE1587s4Mos8EsT1sqNemu4l4535P+jYicwG1m2MAesquAHhIIAyY9iGID576ehX0/34rCCeGuVZablpL+2ki6cEwxPVlH7xtWNIc1AdxivHjkWorkWC1LrbfcNdbZhUrNuz7DZsxHP2sr+2TQdD4L9CA2bgpj6HeQt+MTfCf2PKSdVoLFdwnM8638jHL6MVcEJxeIow/YUDZGEAyR743RdRk4CGU1bJ7er9M1Q4hFfYWGOBsLBok2XXUJcchLgWET1eKdA==");
// the signature length have to be 256 bytes
System.out.print("Signature length 256 = ");
System.out.println(signature.length);
// the data used the generate the signature
data = "some text that you want to be trusted".getBytes();
// verify if signature is ok
try {System.out.println(verify(data,signature,publicKey));}catch(GeneralSecurityException e){e.printStackTrace();}
// if any byte of data changes (ex: change last byte from d to D)
data = "some text that you want to be trusteD".getBytes();
// the signature doesn't math and method verify will fail
try {System.out.println(verify(data,signature,publicKey));}catch(GeneralSecurityException e){e.printStackTrace();}
}
private static boolean verify(byte[] data, byte[] signature, String publicKey) throws GeneralSecurityException{
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(DatatypeConverter.parseBase64Binary(publicKey));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);
Signature sig = Signature.getInstance("SHA256withRSA");
sig.initVerify(pubKey);
sig.update(data);
return sig.verify(signature);
}
}
您可以使用openssl命令行工具創建私鑰和公鑰:
openssl genrsa -des3 -out encrypted.pem 2048
openssl rsa -in encrypted.pem -out private.pem -outform PEM
openssl rsa -in private.pem -pubout > public.pem
您可以使用openssl命令行工具使用私鑰創建一個簽名:
/bin/echo -n "some text that you want to be trusted" > data.txt
openssl dgst -sha256 -sign private.pem data.txt > signature.tmp
您可以使用openssl命令行工具驗證簽名是否正確:
openssl dgst -sha256 -verify public.pem -signature signature.tmp data.txt
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.