如何用org.apache.commons.codec.binary.Base64替换android.util.Base64?

How to replace android.util.Base64 by org.apache.commons.codec.binary.Base64?

我正在将我的原生 Android 游戏迁移到 libGDX。所以我无法再访问 Android 库,我正在尝试用 org.apache.commons.codec.binary.Base64 替换 android.util.Base64。 (我需要 Base64 的 encodeToStringdecode 方法。)

不幸的是,使用新包时出现此错误: java.security.InvalidKeyException: Illegal key size(使用与之前相同的 24 个字符的密钥)。

在 Whosebug 上 they say 可能是因为缺少 "Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 7"。但是如果我使用它们,我的应用程序的用户也必须安装它们。

有没有更简单的解决方案?为什么以前有效?

编辑:

这是导致 InvalidKeyException:

的代码
javax.crypto.Cipher writer = Cipher.getInstance("AES/CBC/PKCS5Padding");

String keyOf24Chars = "abcdefghijklmnopqrstuvwx";

IvParameterSpec ivSpec = getIv();

MessageDigest md = MessageDigest.getInstance("SHA-256");
md.reset();
byte[] keyBytes = md.digest(keyOf24Chars.getBytes("UTF-8"));

SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES/CBC/PKCS5Padding");

// secretKey.getAlgorithm(): "AES/CBC/PKCS5Padding"
// secretKey.getFormat(): "RAW"
// secretKey.getEncoded().length: 32

writer.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec); // java.security.InvalidKeyException: Illegal key size

编辑 2:

正如 Maarten Bodewes 的评论中所解释的,Android 有自己的 javajavax 类 实现,这显然对 32 字节密钥没有问题。在我安装 "JCE Unlimited Strength Jurisdiction Policy Files 7" 之后,我们将看到使用 Base64 并导致此错误的代码:java.lang.NoSuchMethodError: org.apache.commons.codec.binary.Base64.encodeToString:

String valueToEncode = "xyz";
byte[] secureValue;
try {
    secureValue = writer.doFinal(valueToEncode.getBytes("UTF-8"));
} catch (Exception e) {
    throw new SecurePreferencesException(e);
}
Base64 base64 = new Base64();
String secureValueEncoded = base64.encodeToString(secureValue);

但是这种方法确实存在(在 Base64 扩展的 BaseNCodec 中):

public String encodeToString(final byte[] pArray) {
    return StringUtils.newStringUtf8(encode(pArray));
}

如何让Android使用这个方法?

编辑 3:

最后我通过编写一个接口然后使用我的旧 Android 代码(为 Android 编译时)解决了我的问题。检查 libGDX 这个例子:Interfacing with platform specific code.

不,没有更简单的解决方案。您可以使用 3DES 而不是 AES(我假设您正在使用),但您会降低安全性,并且仍然与以前的代码不兼容。将 AES 的安全性降级到 128 是一个更好的主意,但不兼容问题不会消失。

如果您没有在第三方库中使用 encryption/decryption(例如用于 SSL 的 JSSE 或 XML 加密),那么您可以直接使用 Bouncy Castle 或 Spongy Castle API的。所以这意味着直接使用 AESBlockCipher + 一种加密方式。 Bouncy Castle 没有这些限制 - 它们是 Oracle Cipher 实现的一部分。

它之前是有效的,因为 Android 没有这些限制,而 Java 7/8 SE 有。