2011-10-25 31 views
1

我正在閱讀很多內容,因爲我的Android應用程序實現了加密/解密算法。我正在實施從我的網站下載並存儲在我的Android設備的外部存儲中的許可密鑰。應用程序讀取文件的內容並使用服務器公鑰對其進行解密(是的,我知道我應該使用客戶端私鑰,但對我的目的來說沒關係)。問題在於最終的字符串裏面有許多帶問號的黑色方塊。我已經在stackoverflow上讀過很多其他帖子,但我認爲「唯一」的問題是,即使字符串中應該有10個字符,該字符串也是長255字節(具有2048位RSA密鑰)和剩下的字符充滿黑色「」。爲什麼newPlainText var不如「Hello World!」 ?下面我的代碼...非常感謝提前!Java Android - 已解密的字節數組長度爲255字節,而不是「Hello World!」長度

public boolean licenseValid() throws IOException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException{ 
    java.io.File file = new java.io.File(Environment.getExternalStorageDirectory().toString() , 
      "/folder/file.lic"); 
    byte[] fileBArray = new byte[(int)file.length()]; 
    FileInputStream fis = new FileInputStream(file); 

    // Read in the bytes 
    int offset = 0; 
    int numRead = 0; 
    while (offset < fileBArray.length 
      && (numRead=fis.read(fileBArray, offset, fileBArray.length-offset)) >= 0) { 
     offset += numRead; 
    } 

    // Ensure all the bytes have been read in 
    if (offset < fileBArray.length) { 
     throw new IOException("Could not completely read file "+file.getName()); 
    } 

    fis.close(); 

    // Decrypt the ciphertext using the public key 
PublicKey pubKey = readKeyFromFile(); 
Cipher cipher = Cipher.getInstance("RSA"); 
cipher.init(Cipher.DECRYPT_MODE, pubKey); 
byte[] newPlainText = cipher.doFinal(fileBArray); 

    // THE FOLLOWING TOAST PRINTS MANY <?> AND THAN THE DECRYPTED MESSAGE. THE TOTAL NUMBER OF CHARACTERS IS 255, EVEN IF I CHANGE ENCRYPTED TEXT! 
toast(String.valueOf(cipher.doFinal(fileBArray).length)); 

    if (new String(newPlainText, "utf-8").compareTo("Hello World!") == 0) 
     return true; 
    else 
     return false; 
} 

PublicKey readKeyFromFile() throws IOException { 
    Resources myResources = getResources(); 
    //public key filename "pub.lic" 
    InputStream is = myResources.openRawResource(R.raw.pub); 
ObjectInputStream oin = 
    new ObjectInputStream(new BufferedInputStream(is)); 

try { 
     BigInteger m = (BigInteger) oin.readObject(); 
     BigInteger e = (BigInteger) oin.readObject(); 
     RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m, e); 
    KeyFactory fact = KeyFactory.getInstance("RSA"); 
    PublicKey pubKey = fact.generatePublic(keySpec); 
    return pubKey; 
    } catch (Exception e) { 
    throw new RuntimeException("Spurious serialisation error", e); 
    } finally { 
    oin.close(); 
    } 
} 

回答

2

如果使用RSA進行加密,則輸入和輸出始終與密鑰的長度相同。在你的情況下,應該是256字節(= 2048位),所以首先檢查你的代碼,你錯過了一個字節。 當輸入較短時,您需要應用填充,看起來您的服務器和客戶端正在使用不同的填充。 Cipher.getInstance("RSA")將使用平臺默認值,這對於Android和Java SE可能不同。您需要在兩個程序中明確指定填充以使其工作。事情是這樣的:

Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding");

順便說一句,你真的不希望分發與您的應用程序的私人關鍵,所以使用公共密鑰是做正確的事。 (不管你的整個加密方案是否安全,都是另一回事)。

+0

與嘗試: 「RSA /無/ PKCS1Padding」 它給了我下面的錯誤: 異常線程 「main」 java.security.NoSuchAlgorithmException:找不到任何配套商RSA /無/ PKCS1Padding。可能你認爲可能是真正的問題......我現在可以嘗試什麼? – Vale

+0

這是在Android上還是在您的服務器上?您可能需要安裝BouncyCastle提供程序並明確地使用它:'Cipher.getInstance(「RSA/NONE/PKCS1Padding」,「BC」);' –

+0

嗨,我創建pub.key,priv.key和文件。我在我的筆記本電腦上,並比我把pub.key放在Android項目的res-> raw文件夾和我的Android設備的外部存儲器上的文件夾中的file.lic。我在網上讀到Android沒有嵌入BouncyCastle。我想這只是一個填充問題...我可以嘗試什麼? – Vale

相關問題