1

我有来自 .NET Web 服务的以下 RSA XML 字符串

<RSAKeyValue>
    <Modulus>+Tir6+unMOaQ5tHqjjjwnlAMhccnCSMFEi3a0mhIxbW+O/GukjomGyzckQT2h0Ys70JezHbNq5YS3sYkNF29kCkz4HuNfy9eEjE/clA9/zyfT8ZcbnusLcLz2xNgbTp62fQdzBnReI5+dpj/N24krYvHaYIr8ACxDqBv2TR3E9M=</Modulus>
    <Exponent>AQAB</Exponent>
</RSAKeyValue>

当我使用它在 java 中进行 RSA 加密时,我从他们的 Web 服务返回以下错误

javax.xml.ws.soap.SOAPFaultException: Server was unable to process request. ---> Response Code: 100 Message: Invalid authentication credentials ---> Exception of type 'Capita.HSE.GS.Entities.Exceptions.NotificationException' was thrown.
at com.sun.xml.internal.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.java:178)
at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:111)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:108)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:78)
at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:107)
at $Proxy32.checkEngineerDetailSecure(Unknown Source)
at TestWebService.main(TestWebService.java:98)

奇怪的是,如果他们给我一个我想要加密的字符串的加密版本并将其传回给他们,它就可以工作。我的加密代码是

    private static String rsaEncryptPassword(String modulus, String exponent, String password) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException,
        NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {

    byte[] modulusBytes = Base64.decodeBase64(modulus.getBytes());
    byte[] exponentBytes = Base64.decodeBase64(exponent.getBytes());

    BigInteger modulusInt = new BigInteger(1, modulusBytes);
    BigInteger exponentInt = new BigInteger(1, exponentBytes);

    RSAPublicKeySpec rsaPubKey = new RSAPublicKeySpec(modulusInt, exponentInt);
    KeyFactory fact = KeyFactory.getInstance("RSA");
    PublicKey pubKey = fact.generatePublic(rsaPubKey);

    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
    cipher.init(Cipher.ENCRYPT_MODE, pubKey);

    byte[] cipherData = cipher.doFinal(password.getBytes());

    byte[] encryptedBytes = Base64.encodeBase64(cipherData);

    String encryptedString = new String(encryptedBytes);
    System.out.println(encryptedString);

    return encryptedString;
}

在阅读了所有表格和帮助网站后,我不知道为什么这不起作用。任何帮助将不胜感激。

4

1 回答 1

1

我们终于解决了这个问题。事实证明,.Net 服务使用的是 Unicode UTF-16 编码。因此,当我们获取字符串的字节时,我们必须将其设为 UTF-16。但是 UTF-16 字节数组有多种格式。有 UTF-16LE、UTF-16BE 和 UTF-16。

在我们的例子中,当我们将字符串转换为字节数组时,我们必须使用 UTF-16LE。所以最后,解决方案是

byte[] cipherData = cipher.doFinal(password.getBytes("UTF-16LE"));

使用加密时,请确保您知道解密系统正在使用什么字符编码,并确保这是您在从要加密的字符串生成字节数组时使用的字符编码。

于 2012-11-29T16:15:22.243 回答