![](/img/trans.png)
[英]decrypting in RSA throws BadPaddingException when decrypting a string from file
[英]RSA BadPaddingException when decrypting
我正在使用我在桌面應用程序上生成的公鑰在 java 智能卡上加密一些字節的數據,但是當我嘗試解密桌面上的數據時,我收到BadPaddingException : Data must start with zero
,我讀到這可能是由於使用虛假的私鑰解密數據造成的。
首先,我在桌面應用程序上生成了一個公鑰/私鑰對,並使用以下代碼將它們加載到智能卡上(以BigInteger
類型生成,我將它們轉換為十六進制,並從十六進制轉換為字節數組):
void keyGen(String ID)throws Exception{ // where ID is the name of the user KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); kpg.initialize(512); KeyPair kp = kpg.genKeyPair(); this.pubKey = (RSAPublicKey) kp.getPublic(); this.privKey = (RSAPrivateKey) kp.getPrivate(); KeyFactory fact = KeyFactory.getInstance("RSA"); this.pub = fact.getKeySpec(kp.getPublic(), RSAPublicKeySpec.class); this.priv = fact.getKeySpec(kp.getPrivate(), RSAPrivateKeySpec.class); saveToFile(ID+".pub", pub.getModulus(), pub.getPublicExponent()); saveToFile(ID+".priv", priv.getModulus(), priv.getPrivateExponent()); }
這是 savetofile 函數:
public void saveToFile(String fileName, BigInteger mod, BigInteger exp) throws IOException {
ObjectOutputStream oout = new ObjectOutputStream(
new BufferedOutputStream(new FileOutputStream(fileName)));
try {
oout.writeObject(mod);
oout.writeObject(exp);
} catch (Exception e) {
throw new IOException();
} finally {
oout.close();
}
}
這是用於在智能卡上存儲公鑰的行:
Main.sRmi.setPub(Crypto.hexStringToByteArray(Main.crypto.getPubMod().toString(16)),
toByteArray("0"+Main.crypto.getPubexp().toString(16)));
(在字符串中添加零是因為我們無法將奇數十六進制字符串轉換為字節)
然后我嘗試使用卡內的公鑰加密數據,這是我正在使用的功能:
private Cipher cipherRSA = Cipher.getInstance(Cipher.ALG_RSA_PKCS1, false); private byte[] cipherText = new byte[64]; public byte[] encrypt(byte[] clearText){ cipherRSA.init(rsa_PublicKey, Cipher.MODE_ENCRYPT); cipherRSA.doFinal(clearText, (short)0, (short)clearText.length,cipherText, (short)0 ); return cipherText; }
然后我嘗試在另一個桌面應用程序上獲取這個加密值,並使用我從文件中讀取的私鑰對其進行解密:
這是我從文件中讀取私鑰的方式:
public void init (String ID ) throws FileNotFoundException, IOException, Exception{
Object o[] = openFile(ID+".pub");
setPubMod((BigInteger) o[0]);
setPubexp((BigInteger) o[1]);
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(this.pubMod, this.pubexp);
KeyFactory fact = KeyFactory.getInstance("RSA");
pubKey = (RSAPublicKey) fact.generatePublic(keySpec);
o = openFile(ID+".priv");
setPrivMod((BigInteger) o[0]);
setPrivexp((BigInteger) o[1]);
RSAPrivateKeySpec keySpec1 = new RSAPrivateKeySpec(this.privMod, this.privexp);
fact = KeyFactory.getInstance("RSA");
privKey = (RSAPrivateKey) fact.generatePrivate(keySpec1);
cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
}
在獲取BigInteger
變量中的私鑰后,我使用以下方法解密:
public byte[] rsaDecrypt(byte[] data) throws Exception, BadPaddingException {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privKey);
byte[] clearData = cipher.doFinal(data);
return clearData;
}
總而言之,我創建了一個BigInteger
格式的密鑰對,我將BigInteger
變量保存到兩個 BigInteger 的Serialized
數組中以供其他桌面應用程序使用,然后將它們轉換為 Hexa String
,然后轉換為字節數組我把它放在智能卡里面。
誰能告訴我這個程序有什么問題? 是不是太多了? 有沒有更好的方法來做到這一點?
我想我知道問題出在哪里,它與存儲在智能卡內的密鑰有關,以我所做的方式轉換它顯然不起作用,看看我如何從卡中讀取它並打印出來並得到完全不同的結果,所以現在的問題是,如何將在 java.crypto(在 BigInteger 中)創建的公鑰成功導出到以字節形式存儲公鑰的智能卡?
我找到了這個:
設置鍵的公共指數值。 明文數據格式為 big-endian 和右對齊(最低有效位是最后一個字節的最低有效位)。 輸入指數數據被復制到內部表示中。
那么如何將大整數轉換為這種大端字節格式?
現在我正在嘗試設置公鑰,這是我為此執行的代碼:
public void setPub(byte[] expo,byte[] mod){
rsa_PublicKey.clearKey();
rsa_PublicKey.setExponent(expo, (short)0, (short)expo.length);
rsa_PublicKey.setModulus(mod, (short)0, (short)mod.length);
}
其中 expo 是一個 65 字節數組,mod 是一個由密鑰生成器生成的 3 字節數組,但我收到此錯誤:
Exception in thread "AWT-EventQueue-0" java.lang.UnsatisfiedLinkError: com.sun.javacard.impl.NativeMethods.getCurrentContext()B
at com.sun.javacard.impl.NativeMethods.getCurrentContext(Native Method)
at com.sun.javacard.impl.PrivAccess.getCurrentAppID(PrivAccess.java:454)
at javacard.framework.CardRuntimeException.<init>(CardRuntimeException.java:46)
at javacard.security.CryptoException.<init>(DashoA10*..:25)
at com.sun.javacard.javax.smartcard.rmiclient.CardObjectFactory.throwIt(Unknown Source)
at com.sun.javacard.javax.smartcard.rmiclient.CardObjectFactory.throwException(Unknown Source)
at com.sun.javacard.javax.smartcard.rmiclient.CardObjectFactory.getObject(Unknown Source)
at com.sun.javacard.rmiclientlib.JCRemoteRefImpl.parseAPDU(Unknown Source)
at com.sun.javacard.rmiclientlib.JCRemoteRefImpl.invoke(Unknown Source)
at sid2.CompteurImpl_Stub.setPub(Unknown Source)
at sid2.ServerRmi.setPub(ServerRmi.java:27)
at AddCard$2.actionPerformed(AddCard.java:160)
這就是密鑰 priv 和 pub 的生成方式:
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(512);
KeyPair kp = kpg.genKeyPair();
this.pubKey = kp.getPublic();
this.privKey = kp.getPrivate();
KeyFactory fact = KeyFactory.getInstance("RSA");
this.pub = fact.getKeySpec(kp.getPublic(), RSAPublicKeySpec.class);
this.priv = fact.getKeySpec(kp.getPrivate(), RSAPrivateKeySpec.class);
“其中 expo 是一個 65 字節的數組,mod 是一個由密鑰生成器生成的 3 字節數組,但我收到此錯誤:...”
難怪你會出錯,指數通常比模數短,模數總是與密鑰大小相同。 您正在切換模數和指數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.