在android上,获取xml rsa公钥并使用它加密字符串

时间:2015-07-23 10:37:10

标签: java android encryption

我正在开发一个Android应用程序并从我合作的公司的服务器获取此公钥:

PFJTQUtleVZhbHVlPjxNb2R1bHVzPnZOcFhkRWVOTU5pZDhuOTlUekRGMVo4MDNvTEdRSzlqWnNFODlDd2tiS29GV0tGZmt2QTZKODBNWHhPZnhqbFZIYU8vYWM4YUpMc1AxWVR1RFNHVis3VExQL0puVVpyNlJQQTdpbFlmMitVWExiS0U2ZW1RYzBKdXlOaVArL0FTMGZmKzYwSnZQekhYeEdQQnVIbWtTcmRqdEtFV0JCZXJzWWNuQVJyT2ZSYz08L01vZHVsdXM+PEV4cG9uZW50PkFRQUI8L0V4cG9uZW50PjwvUlNBS2V5VmFsdWU+

服务器是IIS 7.5的窗口。

base64decode它给我这个XML

<RSAKeyValue><Modulus>vNpXdEeNMNid8n99TzDF1Z803oLGQK9jZsE89CwkbKoFWKFfkvA6J80MXxOfxjlVHaO/ac8aJLsP1YTuDSGV+7TLP/JnUZr6RPA7ilYf2+UXLbKE6emQc0JuyNiP+/AS0ff+60JvPzHXxGPBuHmkSrdjtKEWBBersYcnARrOfRc=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>

从这个xml中提取Modulu和Exponent,base64对它们进行编码并制作公钥对象的规范:

    PublicKey pbKey = null;
    XMLParser parser = new XMLParser();
    Document doc = parser.getDomElement(publicKeyString);
    Element rsakeyvalue = doc.getDocumentElement();

    String modulusBase64 = parser.getValue(rsakeyvalue, "Modulus");
    byte[] modulus = Base64.decode(modulusBase64, 0);

    String exponentBase64 = parser.getValue(rsakeyvalue, "Exponent");
    byte[] exponent = Base64.decode(exponentBase64, 0);

    BigInteger modBigInteger = new BigInteger(1,modulus);
    BigInteger exBigInteger = new BigInteger(1,exponent);

    RSAPublicKeySpec spec = new RSAPublicKeySpec(modBigInteger, exBigInteger);
    try {
        KeyFactory factory = KeyFactory.getInstance("RSA");
        pbKey = factory.generatePublic(spec);
    } catch (Exception e) {
        e.printStackTrace();
    }

创建密码并添加纯文本以加密:

    Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC");

    byte[] keyBytes =   Base64.decode(this.publicKey, 0);

    /* the strToPublicKey is the previews code block */
    PublicKey publickey = strToPublicKey(new String(keyBytes));
    cipher.init( Cipher.ENCRYPT_MODE , publickey );

    // Base 64 encode removed.
    //byte[] encryptedBytes = Base64.encode( cipher.doFinal(plainText.getBytes()), 0 );
    byte[] encryptedBytes = cipher.doFinal(plainText.getBytes());

这里的一切都在运作,但服务器不接受它, 我对base64进行编码并将其作为字节数组发送。

服务器管理员说它太长了,应该是128位但是它有174位...... 我做错了什么?

它如何称为这个键? RSA XML是正确的吗?或者它有其他名字?

如果有人知道如何使用它,我也可以从服务器获取PEM字符串。

修改 我忘了在这里放一个重要的部分,我将数据作为字节数组发送到服务器,这就是我如何制作它的字符串:

public static int unsignedToBytes(byte b) {
    return b & 0xFF;
}
StringBuilder byteArrayString = new StringBuilder();
int bytesLength = bytes.length;
int bytesCounter = 0;
for (byte aByte : bytes) {
    bytesCounter++;
    byteArrayString.append(unsignedToBytes(aByte));
    if(bytesCounter < bytesLength){
        byteArrayString.append(",");
    }
}

解决了! - 解决方案: 字符串生成器使用的字节是有符号的,所以我使用这个函数unsignedToBytes()使它们无符号,我删除了encrypt()函数的base64Encription。 这就是问题,我希望它能帮到其他任何人。

1 个答案:

答案 0 :(得分:1)

你的变量命名很糟糕。 encryptedBytes不包含加密字节,而是包含base64编码中的加密字节。

这是你没有得到预期结果的原因。

应用Base64编码之前加密数据的长度为128字节。

之后长度为172个字节。