Java Android - 解密的字节数组长255个字节而不是“Hello World!”。长度

时间:2011-10-25 01:14:51

标签: android utf-8 encryption

我几周以来一直在阅读为我的Android应用程序实现加密/解密算法。我正在实施从我的网站下载并存储在我的Android设备的外部存储中的许可证密钥。应用程序读取文件的内容并使用服务器公钥解密(是的,我知道我应该使用客户端私钥,但它可以用于我的目的)。问题是最终的字符串有很多带有问号的黑色方块。我已经在stackoverflow上阅读了很多其他帖子,但我认为“唯一”的问题是,即使字符串中应该有10个字符,字符串也是长255字节(带有2048位RSA密钥)和其余的字符都是黑色的“”。为什么newPlainText var不长为“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();
   }
}

1 个答案:

答案 0 :(得分:2)

如果使用RSA加密,则输入和输出的长度始终与密钥相同。在你的情况下,这应该是256字节(= 2048位),所以首先检查你的代码,你缺少一个字节。 当输入较短时,您需要应用填充,看起来您的服务器和客户端使用不同的填充。 Cipher.getInstance("RSA")将使用平台默认值,这可能与Android和Java SE不同。您需要在两个程序中明确指定填充才能使其正常工作。像这样:

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

顺便说一下,你真的不想在你的应用程序中分发私有密钥,所以使用公钥是正确的。 (无论您的整个加密方案是否安全,都是另一回事。)