You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android AES/GCM加解密传递IV参数及解密实现问题求助

Android 加解密IV参数传递与功能实现

我正在开发Android加解密相关功能,希望能得到代码相关的帮助。我需要在加密、解密流程中传递IV(初始向量)参数:

加密函数初始实现

我最初尝试将加密后的密文与IV分别做Base64编码后用分号拼接输出,代码如下:

encryptedText.setText(Base64.encodeToString(vals, Base64.DEFAULT) + ";" + (Base64.encodeToString(encryptionIv, Base64.DEFAULT)));

从运行结果来看该逻辑运行正常,完整加密代码如下:

public void encryptString(String alias) {
        try {
            KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
            keyStore.load(null);
            SecretKey secretKey = (SecretKey) keyStore.getKey(alias, null);
            String initialText = startText.getText().toString();
            if(initialText.isEmpty()) {
                Toast.makeText(this, "请在'初始文本'输入框内输入内容", Toast.LENGTH_LONG).show();
                return;
            }
            Cipher inCipher = Cipher.getInstance("AES/GCM/NoPadding");
            inCipher.init(Cipher.ENCRYPT_MODE, secretKey);
            byte[] src= initialText.getBytes("UTF-8");
            byte[] iv = inCipher.getIV();
            assert iv.length == 12;
            byte[] cipherText = inCipher.doFinal(src);
            assert cipherText.length == src.length + 16;
            byte[] message = new byte[12 + src.length + 16];
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            CipherOutputStream cipherOutputStream = new CipherOutputStream(
                    outputStream, inCipher);
            cipherOutputStream.write(src);
            cipherOutputStream.close();
            byte [] vals = outputStream.toByteArray();
            encryptedText.setText(Base64.encodeToString(vals, Base64.DEFAULT));
        } catch (Exception e) {
            Toast.makeText(this, "发生异常:" + e.getMessage(), Toast.LENGTH_LONG).show();
            Log.e(TAG, Log.getStackTraceString(e));
        }
    }

能否帮忙提供可以正常运行的解密示例?感谢。

更新内容

我参考示例调整了IV传递逻辑,当前加密代码如下(RSA方案):

public void encryptString(String alias) {
        try {
            KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null);
            RSAPublicKey publicKey = (RSAPublicKey) privateKeyEntry.getCertificate().getPublicKey();

            String initialText = startText.getText().toString();
            if(initialText.isEmpty()) {
                Toast.makeText(this, "请在'初始文本'组件内输入内容", Toast.LENGTH_LONG).show();
                return;
            }

            Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL");
            inCipher.init(Cipher.ENCRYPT_MODE, publicKey);

            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            CipherOutputStream cipherOutputStream = new CipherOutputStream(
                    outputStream, inCipher);
            cipherOutputStream.write(initialText.getBytes("UTF-8"));
            cipherOutputStream.close();

            byte [] vals = outputStream.toByteArray();
            encryptedText.setText(Base64.encodeToString(vals, Base64.DEFAULT));
        } catch (Exception e) {
            Toast.makeText(this, "发生异常:" + e.getMessage(), Toast.LENGTH_LONG).show();
            Log.e(TAG, Log.getStackTraceString(e));
        }
    }

最新更新

加密代码

我调整为AES/GCM方案,将12位IV拼接在密文前组合后再Base64编码输出,代码如下:

public void encryptString(String alias) {
        try {
            KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
            keyStore.load(null);
            SecretKey secretKey = (SecretKey) keyStore.getKey(alias, null);
            String initialText = startText.getText().toString();
            if(initialText.isEmpty()) {
                Toast.makeText(this, "请在'初始文本'输入框内输入内容", Toast.LENGTH_LONG).show();
                return;
            }
            Cipher inCipher = Cipher.getInstance("AES/GCM/NoPadding");
            inCipher.init(Cipher.ENCRYPT_MODE, secretKey);
            byte[] src= initialText.getBytes("UTF-8");
            byte[] iv = inCipher.getIV();
            assert iv.length == 12;
            byte[] cipherText = inCipher.doFinal(src);
            assert cipherText.length == src.length + 16;
            byte[] message = new byte[12 + src.length + 16];
            System.arraycopy(iv, 0, message, 0, 12);
            System.arraycopy(cipherText, 0, message, 12, cipherText.length);
            encryptedText.setText(Base64.encodeToString(message, Base64.DEFAULT));
        } catch (Exception e) {
            Toast.makeText(this, "发生异常:" + e.getMessage(), Toast.LENGTH_LONG).show();
            Log.e(TAG, Log.getStackTraceString(e));
        }
    }

解密代码(无法正常运行)

public void decryptString(String alias) {
        try {
            KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
            keyStore.load(null);
            SecretKey secretKey = (SecretKey) keyStore.getKey(alias, null);
            String cipherText = encryptedText.getText().toString();

            byte[] src = cipherText.getBytes();
            byte[] message = new byte[12 + src.length + 16];
            Cipher output = Cipher.getInstance("AES/GCM/NoPadding");
            GCMParameterSpec params = new GCMParameterSpec(128, message, 0, 12);
            output.init(Cipher.DECRYPT_MODE, secretKey, params);
            CipherInputStream cipherInputStream = new CipherInputStream(
             new ByteArrayInputStream(Base64.decode(cipherText, Base64.DEFAULT)), output);
            ArrayList<Byte> values = new ArrayList<>();
           int nextByte;
           while ((nextByte = cipherInputStream.read()) != -1) {
                values.add((byte)nextByte);
            }
          byte[] bytes = new byte[values.size()];
         for(int i = 0; i < bytes.length; i++) {
            bytes[i] = values.get(i).byteValue();
         }
            String finalText = new String(bytes, 0, bytes.length, "UTF-8");
            decryptedText.setText(finalText);
        } catch (Exception e) {
            Toast.makeText(this, "发生异常:" + e.getMessage(), Toast.LENGTH_LONG).show();
            Log.e(TAG, Log.getStackTraceString(e));
        }
    }

运行时报错,能否帮忙排查问题?


最终解决方案

加密函数

public void encryptString(String alias) {
        try {
            KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
            keyStore.load(null);
            SecretKey secretKey = (SecretKey) keyStore.getKey(alias, null);
            String initialText = startText.getText().toString();
            if(initialText.isEmpty()) {
                Toast.makeText(this, "请在'初始文本'输入框内输入内容", Toast.LENGTH_LONG).show();
                return;
            }
            Cipher inCipher = Cipher.getInstance("AES/GCM/NoPadding");
            inCipher.init(Cipher.ENCRYPT_MODE, secretKey);
            byte[] src= initialText.getBytes("UTF-8");
            byte[] iv = inCipher.getIV();
            assert iv.length == 12;
            byte[] cipherText = inCipher.doFinal(src);
            assert cipherText.length == src.length + 16;
            byte[] message = new byte[12 + src.length + 16];
            System.arraycopy(iv, 0, message, 0, 12);
            System.arraycopy(cipherText, 0, message, 12, cipherText.length);
            encryptedText.setText(Base64.encodeToString(message, Base64.DEFAULT));
        } catch (Exception e) {
            Toast.makeText(this, "发生异常:" + e.getMessage(), Toast.LENGTH_LONG).show();
            Log.e(TAG, Log.getStackTraceString(e));
        }
    }

解密函数

public void decryptString(String alias) {
        try {
            KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
            keyStore.load(null);
            SecretKey secretKey = (SecretKey) keyStore.getKey(alias, null);
            String cipherText = encryptedText.getText().toString();
            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
            byte[] nonceCiphertextTag = Base64.decode(cipherText, Base64.DEFAULT);
            GCMParameterSpec params = new GCMParameterSpec(128, nonceCiphertextTag, 0, 12);
            cipher.init(Cipher.DECRYPT_MODE, secretKey, params);
            byte[] decrypted = cipher.doFinal(nonceCiphertextTag, 12, nonceCiphertextTag.length - 12);
            String finalText = new String(decrypted, 0, decrypted.length, "UTF-8");
            decryptedText.setText(finalText);
        } catch (Exception e) {
            Toast.makeText(this, "发生异常:" + e.getMessage(), Toast.LENGTH_LONG).show();
            Log.e(TAG, Log.getStackTraceString(e));
        }
    }

非常感谢@Topaco的帮助。


内容的提问来源于stack exchange,提问作者Xshell

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 04:45:02