java - 使用 String IV 进行 AES 加密

标签 java android encryption aes

现在我正在使用 scotabb libs AESCryptor对于我的 Android 项目中的 AES 加密,

我真的需要字符串 IV bcs 我在 swift(IOS) 中的其他项目和使用 AES 加密/解密 256 和字符串 IV 的网络服务 (c#)。

但在 scotabb aesencriptor 中使用空白 IV。

是否可以将空白IV(字节)更改为16长度的字符串? 以及如何做到这一点?

这是我的课

public final class AEScrypt{

private static final String TAG = "AESCrypt";

//AESCrypt-ObjC uses CBC and PKCS7Padding
private static final String AES_MODE = "AES/CBC/PKCS7Padding";
private static final String CHARSET = "UTF-8";

//AESCrypt-ObjC uses SHA-256 (and so a 256-bit key)
private static final String HASH_ALGORITHM = "SHA-256";

//AESCrypt-ObjC uses blank IV (not the best security, but the aim here is compatibility)
private static final byte[] ivBytes = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
//togglable log option (please turn off in live!)
public static boolean DEBUG_LOG_ENABLED = false;



private static SecretKeySpec generateKey(final String password) throws NoSuchAlgorithmException, UnsupportedEncodingException {
    final MessageDigest digest = MessageDigest.getInstance(HASH_ALGORITHM);
    byte[] bytes = password.getBytes("UTF-8");
    digest.update(bytes, 0, bytes.length);
    byte[] key = digest.digest();

    log("SHA-256 key ", key);

    SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
    return secretKeySpec;
}


public static String encrypt(final String password, String message)
        throws GeneralSecurityException {

    try {
        final SecretKeySpec key = generateKey(password);

        log("message", message);

        byte[] cipherText = encrypt(key, ivBytes, message.getBytes(CHARSET));

        //NO_WRAP is important as was getting \n at the end
        String encoded = Base64.encodeToString(cipherText, Base64.NO_WRAP);
        log("Base64.NO_WRAP", encoded);
        return encoded;
    } catch (UnsupportedEncodingException e) {
        if (DEBUG_LOG_ENABLED)
            Log.e(TAG, "UnsupportedEncodingException ", e);
        throw new GeneralSecurityException(e);
    }
}

public static byte[] encrypt(final SecretKeySpec key, final byte[] iv, final byte[] message)
        throws GeneralSecurityException {
    final Cipher cipher = Cipher.getInstance(AES_MODE);
    IvParameterSpec ivSpec = new IvParameterSpec(iv);
    cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
    byte[] cipherText = cipher.doFinal(message);

    log("cipherText", cipherText);

    return cipherText;
}



public static String decrypt(final String password, String base64EncodedCipherText)
        throws GeneralSecurityException {

    try {
        final SecretKeySpec key = generateKey(password);

        log("base64EncodedCipherText", base64EncodedCipherText);
        byte[] decodedCipherText = Base64.decode(base64EncodedCipherText, Base64.NO_WRAP);
        log("decodedCipherText", decodedCipherText);

        byte[] decryptedBytes = decrypt(key,  ivBytes, decodedCipherText);

        log("decryptedBytes", decryptedBytes);
        String message = new String(decryptedBytes, CHARSET);
        log("message", message);


        return message;
    } catch (UnsupportedEncodingException e) {
        if (DEBUG_LOG_ENABLED)
            Log.e(TAG, "UnsupportedEncodingException ", e);

        throw new GeneralSecurityException(e);
    }
}


public static byte[] decrypt(final SecretKeySpec key, final byte[] iv, final byte[] decodedCipherText)
        throws GeneralSecurityException {
    final Cipher cipher = Cipher.getInstance(AES_MODE);
    IvParameterSpec ivSpec = new IvParameterSpec(iv);
    cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
    byte[] decryptedBytes = cipher.doFinal(decodedCipherText);

    log("decryptedBytes", decryptedBytes);

    return decryptedBytes;
}


private static void log(String what, byte[] bytes) {
    if (DEBUG_LOG_ENABLED)
        Log.d(TAG, what + "[" + bytes.length + "] [" + bytesToHex(bytes) + "]");
}

private static void log(String what, String value) {
    if (DEBUG_LOG_ENABLED)
        Log.d(TAG, what + "[" + value.length() + "] [" + value + "]");
}

private static String bytesToHex(byte[] bytes) {
    final char[] hexArray = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
            '9', 'A', 'B', 'C', 'D', 'E', 'F'};
    char[] hexChars = new char[bytes.length * 2];
    int v;
    for (int j = 0; j < bytes.length; j++) {
        v = bytes[j] & 0xFF;
        hexChars[j * 2] = hexArray[v >>> 4];
        hexChars[j * 2 + 1] = hexArray[v & 0x0F];
    }
    return new String(hexChars);
}

private AESCrypt() {
}

}

最佳答案

您可以将 IV 更改为您想要的任何 16 字节值。您可以看到静态 IV(一个想法)在类级别定义为 0x00 * 16。您可以将该字节数组替换为另一个值,可以是原始字节或解码后的十六进制或 Base64 值等。

您应该为每个加密操作提供唯一且不可预测的 IV,并将 IV 与密文一起传递以用于解密。 IV 不需要保护或加密,可以与密文一起明文传输。

关于java - 使用 String IV 进行 AES 加密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41501337/

相关文章:

java - 将正则表达式与数组进行匹配

android - Gradle 构建 VS Eclipse 构建

javascript - 如何使用 AES 在 javascript 中使用 cbc 模式

Java JPA 属性为空

java - 一维数组不在 for 循环中打印,始终等于 0

android - 动画不会在当前可见的 ListView 项目中启动

java - 从 Android 中的 AsyncTask 返回一个值

java - Android:定义要使用的加密方式:AES 128 或 AES 256

postgresql - Keycloak可以存储在postgres中加密的用户数据吗

java - 我应该将 slf4j 的 simplelogger 的属性文件放在哪里?