gpt4 book ai didi

Android AES/GCM/NoPadding 特定长度输入字节的错误?

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:03:02 26 4
gpt4 key购买 nike

我写了一个类,用于对任意数据进行解密和加密。

它是这样工作的:因为 AndroidKeyStore 生成的 AES key 在卸载应用程序后“丢失”,我们有一个公钥/私钥对,其中公钥包含在应用程序中。出于失败保存的目的,它用于加密 AES key ,该 key 沿着 IV 填充在每个加密消息的前面。这样我们就可以用我们的私钥恢复 AES key

在单元测试中,我发现它适用于大多数输入。奇怪的是,在某些字节数组长度上它失败了(我发现即 81920、131073。)

这是 AESCrypto 代码:

package com.mycompany.appname.crypto;

import android.content.Context;
import android.content.SharedPreferences;
import android.security.keystore.KeyProperties;
import android.security.keystore.KeyProtection;
import android.support.annotation.NonNull;
import android.util.Base64;
import android.util.Log;

import com.mycompany.appname.R;

import java.io.DataInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AesGcmCrypto implements Crypto{

public static final String TAG = AesGcmCrypto.class.getSimpleName();

private static final String KEY_ALIAS = "OI1lTI1ITLI1l0";

private static final String PREF_NAME = "CryptoPrefs";
private static final String KEY_ENCRYPTED_SECRET = "encryptedSecret";

private static final String ANDROID_KEY_STORE = "AndroidKeyStore";
private static final String PUBLIC_KEY_ASSET = "public_key.der";

private static final int IV_SIZE = 12;

private static final String AES = KeyProperties.KEY_ALGORITHM_AES;
private static final String AES_BLOCK_MODE = KeyProperties.BLOCK_MODE_GCM;
private static final String AES_PADDING = KeyProperties.ENCRYPTION_PADDING_NONE;
private static final String AES_MODE = AES + "/" + AES_BLOCK_MODE + "/" + AES_PADDING;
//generate key, possible values 128 bit key (16), 192(24), 256(32)
private static final int AES_KEY_SIZE = 32;
private static final int AES_TAG_LEN = 128;

private static final String RSA = KeyProperties.KEY_ALGORITHM_RSA;
private static final String RSA_BLOCK_MODE = KeyProperties.BLOCK_MODE_ECB;
private static final String RSA_PADDING = KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1;
private static final String RSA_MODE = RSA + "/" + RSA_BLOCK_MODE + "/" + RSA_PADDING;
private static final String RSA_PROVIDER = "AndroidOpenSSL";


private final Context mContext;
private final SharedPreferences mPrefs;

private SecureRandom mSecureRandom;
private KeyStore mAndroidKeyStore;
private PublicKey mPublicKey;
private byte[] mEncryptedSecretKey;

public AesGcmCrypto(Context context) {
mContext = context;
mSecureRandom = new SecureRandom();
mPrefs = mContext.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
try {
mAndroidKeyStore = KeyStore.getInstance(ANDROID_KEY_STORE);
mAndroidKeyStore.load(null);

} catch (KeyStoreException e) {
Log.wtf(TAG, mContext.getString(R.string.err_keystore_not_avail), e);
} catch (Exception e) {
Log.wtf(TAG, mContext.getString(R.string.err_keystore_not_loadable), e);
}
}

void reset() throws KeyStoreException {
mAndroidKeyStore.deleteEntry(KEY_ALIAS);
}

@Override
public byte[] encrypt(byte[] message) throws GeneralSecurityException{
Cipher cipher = Cipher.getInstance(AES_MODE);
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey());
GCMParameterSpec parameterSpec = cipher.getParameters().getParameterSpec(GCMParameterSpec.class);
byte[] cryptedBytes = cipher.doFinal(message);
byte[] iv = parameterSpec.getIV();
byte[] encryptedSecretKey = getEncryptedSecretKey();
return ByteBuffer.allocate(iv.length + encryptedSecretKey.length + cryptedBytes.length)
.put(iv)
.put(encryptedSecretKey)
.put(cryptedBytes)
.array();
}

@Override
public byte[] decrypt(byte[] bytes) throws GeneralSecurityException{
ByteBuffer buffer = ByteBuffer.wrap(bytes);
byte[] iv = new byte[IV_SIZE];
buffer.get(iv);

//skip aes key bytes
byte[] irrelevant = new byte[AES_KEY_SIZE * 8];
buffer.get(irrelevant);

byte[] encryptedMessage = new byte[bytes.length - IV_SIZE - irrelevant.length];
buffer.get(encryptedMessage);

Cipher cipher = Cipher.getInstance(AES_MODE);
GCMParameterSpec parameterSpec = new GCMParameterSpec(AES_TAG_LEN, iv);
cipher.init(Cipher.DECRYPT_MODE, getSecretKey(), parameterSpec);
byte[] decryptedMessage = cipher.doFinal(encryptedMessage);
return decryptedMessage;
}

public PublicKey getPublicKey() {
if (null == mPublicKey) {
mPublicKey = readPublicKey();
}
return mPublicKey;
}

public byte[] getEncryptedSecretKey() {
if (null == mEncryptedSecretKey){
mEncryptedSecretKey = Base64.decode(mPrefs.getString(KEY_ENCRYPTED_SECRET, null), Base64.NO_WRAP);
}
return mEncryptedSecretKey;
}

private void saveEncryptedSecretKey(byte[] encryptedSecretKey){
String base64EncryptedKey = Base64.encodeToString(encryptedSecretKey, Base64.NO_WRAP);
mPrefs.edit().putString(KEY_ENCRYPTED_SECRET, base64EncryptedKey).apply();
}

protected SecretKey getSecretKey(){
SecretKey secretKey = null;
try {
if (!mAndroidKeyStore.containsAlias(KEY_ALIAS)){
generateAndStoreSecureKey();
}
secretKey = (SecretKey) mAndroidKeyStore.getKey(KEY_ALIAS, null);
} catch (KeyStoreException e) {
Log.wtf(TAG, mContext.getString(R.string.err_keystore_aliasing_forbidden), e);
} catch (GeneralSecurityException e) {
e.printStackTrace();
}
return secretKey;
}

private void generateAndStoreSecureKey()
throws NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException, KeyStoreException, BadPaddingException, IllegalBlockSizeException {
//We cannot use AndroidKeyStore Generator, because it keeps its key-bytes inside the secure element
SecretKey secretKey = generateSecureRandomKey();
PublicKey publicKey = getPublicKey();
Cipher keyCipher = Cipher.getInstance(RSA_MODE, RSA_PROVIDER);
keyCipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedSecretKeyBytes = keyCipher.doFinal(secretKey.getEncoded());

saveEncryptedSecretKey(encryptedSecretKeyBytes);

KeyProtection keyProtection = new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT | KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_VERIFY)
.setBlockModes(AES_BLOCK_MODE)
.setEncryptionPaddings(AES_PADDING)
.build();
mAndroidKeyStore.setEntry(KEY_ALIAS, new KeyStore.SecretKeyEntry(secretKey), keyProtection);
}


protected PublicKey readPublicKey() {
DataInputStream dis = null;
PublicKey key = null;
try {
dis = new DataInputStream(mContext.getResources().getAssets().open(PUBLIC_KEY_ASSET));
byte[] keyBytes = new byte[dis.available()];
dis.readFully(keyBytes);

X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
KeyFactory facotory = KeyFactory.getInstance(RSA);
key = facotory.generatePublic(spec);
} catch (Exception e) {
key = null;
} finally {
if (null != dis) {
try {
dis.close();
} catch (IOException e) {
Log.wtf(TAG, mContext.getString(R.string.err_cannot_close), e);
}
}
}
return key;
}

@NonNull
protected SecretKey generateSecureRandomKey() {
return new SecretKeySpec(generateSecureRandomBytes(AES_KEY_SIZE), AES);
}

@NonNull
protected byte[] generateSecureRandomBytes(int byteCount) {
byte[] keyBytes = new byte[byteCount];
mSecureRandom.nextBytes(keyBytes);
return keyBytes;
}
}

单元测试函数如下所示:

 @Test
public void testCrypto() throws Exception{

AesGcmCrypto aesGcmCrypto = new AesGcmCrypto(InstrumentationRegistry.getTargetContext());
aesGcmCrypto.reset();
Random rand = new Random();
byte[] buffer = null;
for (int i = 1024 *20; i < 1024 * 200; i += 1024){
Log.i(TAG, "Testing " + i);
buffer = new byte[i];
rand.nextBytes(buffer);

byte[] encrypt = aesGcmCrypto.encrypt(buffer);
Assert.assertNotNull(encrypt);
decrypt = aesGcmCrypto.decrypt(encrypt);
Assert.assertNotNull(decrypt);
Assert.assertTrue(Arrays.equals(buffer, decrypt));

}

}

哪些日志:

    09-13 00:06:16.034 17222-17238/com.mycompany.appname I/TestRunner: started: testCrypto(com.mycompany.appname.crypto.CryptoTest)
09-13 00:06:16.052 17222-17238/com.mycompany.appname I/CryptoTest: Testing 20480
09-13 00:06:16.205 17222-17238/com.mycompany.appname I/CryptoTest: Testing 21504
09-13 00:06:16.269 17222-17238/com.mycompany.appname I/CryptoTest: Testing 22528
09-13 00:06:16.337 17222-17238/com.mycompany.appname I/CryptoTest: Testing 23552
09-13 00:06:16.406 17222-17238/com.mycompany.appname I/CryptoTest: Testing 24576
09-13 00:06:16.469 17222-17238/com.mycompany.appname I/CryptoTest: Testing 25600
09-13 00:06:16.551 17222-17238/com.mycompany.appname I/CryptoTest: Testing 26624
09-13 00:06:16.632 17222-17238/com.mycompany.appname I/CryptoTest: Testing 27648
09-13 00:06:16.700 17222-17238/com.mycompany.appname I/CryptoTest: Testing 28672
09-13 00:06:16.765 17222-17238/com.mycompany.appname I/CryptoTest: Testing 29696
09-13 00:06:16.839 17222-17238/com.mycompany.appname I/CryptoTest: Testing 30720
09-13 00:06:16.906 17222-17238/com.mycompany.appname I/CryptoTest: Testing 31744
09-13 00:06:16.973 17222-17238/com.mycompany.appname I/CryptoTest: Testing 32768
09-13 00:06:17.043 17222-17238/com.mycompany.appname I/CryptoTest: Testing 33792
09-13 00:06:17.118 17222-17238/com.mycompany.appname I/CryptoTest: Testing 34816
09-13 00:06:17.191 17222-17238/com.mycompany.appname I/CryptoTest: Testing 35840
09-13 00:06:17.266 17222-17238/com.mycompany.appname I/CryptoTest: Testing 36864
09-13 00:06:17.341 17222-17238/com.mycompany.appname I/CryptoTest: Testing 37888
09-13 00:06:17.768 17222-17238/com.mycompany.appname I/CryptoTest: Testing 38912
09-13 00:06:17.850 17222-17238/com.mycompany.appname I/CryptoTest: Testing 39936
09-13 00:06:17.938 17222-17238/com.mycompany.appname I/CryptoTest: Testing 40960
09-13 00:06:18.020 17222-17238/com.mycompany.appname I/CryptoTest: Testing 41984
09-13 00:06:18.098 17222-17238/com.mycompany.appname I/CryptoTest: Testing 43008
09-13 00:06:18.171 17222-17238/com.mycompany.appname I/CryptoTest: Testing 44032
09-13 00:06:18.245 17222-17238/com.mycompany.appname I/CryptoTest: Testing 45056
09-13 00:06:18.672 17222-17238/com.mycompany.appname I/CryptoTest: Testing 46080
09-13 00:06:18.758 17222-17238/com.mycompany.appname I/CryptoTest: Testing 47104
09-13 00:06:18.838 17222-17238/com.mycompany.appname I/CryptoTest: Testing 48128
09-13 00:06:18.914 17222-17238/com.mycompany.appname I/CryptoTest: Testing 49152
09-13 00:06:18.992 17222-17238/com.mycompany.appname I/CryptoTest: Testing 50176
09-13 00:06:19.283 17222-17238/com.mycompany.appname I/CryptoTest: Testing 51200
09-13 00:06:19.434 17222-17238/com.mycompany.appname I/CryptoTest: Testing 52224
09-13 00:06:19.609 17222-17238/com.mycompany.appname I/CryptoTest: Testing 53248
09-13 00:06:19.722 17222-17238/com.mycompany.appname I/CryptoTest: Testing 54272
09-13 00:06:19.832 17222-17238/com.mycompany.appname I/CryptoTest: Testing 55296
09-13 00:06:20.021 17222-17238/com.mycompany.appname I/CryptoTest: Testing 56320
09-13 00:06:20.171 17222-17238/com.mycompany.appname I/CryptoTest: Testing 57344
09-13 00:06:20.335 17222-17238/com.mycompany.appname I/CryptoTest: Testing 58368
09-13 00:06:20.477 17222-17238/com.mycompany.appname I/CryptoTest: Testing 59392
09-13 00:06:20.658 17222-17238/com.mycompany.appname I/CryptoTest: Testing 60416
09-13 00:06:20.812 17222-17238/com.mycompany.appname I/CryptoTest: Testing 61440
09-13 00:06:21.001 17222-17238/com.mycompany.appname I/CryptoTest: Testing 62464
09-13 00:06:21.108 17222-17238/com.mycompany.appname I/CryptoTest: Testing 63488
09-13 00:06:21.267 17222-17238/com.mycompany.appname I/CryptoTest: Testing 64512
09-13 00:06:21.414 17222-17238/com.mycompany.appname I/CryptoTest: Testing 65536
09-13 00:06:21.570 17222-17238/com.mycompany.appname I/CryptoTest: Testing 66560
09-13 00:06:21.731 17222-17238/com.mycompany.appname I/CryptoTest: Testing 67584
09-13 00:06:21.902 17222-17238/com.mycompany.appname I/CryptoTest: Testing 68608
09-13 00:06:22.083 17222-17238/com.mycompany.appname I/CryptoTest: Testing 69632
09-13 00:06:22.255 17222-17238/com.mycompany.appname I/CryptoTest: Testing 70656
09-13 00:06:22.478 17222-17238/com.mycompany.appname I/CryptoTest: Testing 71680
09-13 00:06:22.638 17222-17238/com.mycompany.appname I/CryptoTest: Testing 72704
09-13 00:06:22.840 17222-17238/com.mycompany.appname I/CryptoTest: Testing 73728
09-13 00:06:23.146 17222-17238/com.mycompany.appname I/CryptoTest: Testing 74752
09-13 00:06:23.345 17222-17238/com.mycompany.appname I/CryptoTest: Testing 75776
09-13 00:06:23.647 17222-17238/com.mycompany.appname I/CryptoTest: Testing 76800
09-13 00:06:23.820 17222-17238/com.mycompany.appname I/CryptoTest: Testing 77824
09-13 00:06:23.995 17222-17238/com.mycompany.appname I/CryptoTest: Testing 78848
09-13 00:06:24.200 17222-17238/com.mycompany.appname I/CryptoTest: Testing 79872
09-13 00:06:24.394 17222-17238/com.mycompany.appname I/CryptoTest: Testing 80896
09-13 00:06:24.645 17222-17238/com.mycompany.appname I/CryptoTest: Testing 81920
09-13 00:06:24.849 17222-17238/com.mycompany.appname I/TestRunner: failed: testCrypto3(com.mycompany.appname.crypto.CryptoTest)
----- begin exception -----
09-13 00:06:24.858 17222-17238/com.mycompany.appname I/TestRunner: junit.framework.AssertionFailedError
at junit.framework.Assert.fail(Assert.java:48)
at junit.framework.Assert.assertTrue(Assert.java:20)
at junit.framework.Assert.assertTrue(Assert.java:27)
at com.mycompany.appname.crypto.CryptoTest.testCrypto3(CryptoTest.java:72)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at android.support.test.runner.AndroidJUnit4.run(AndroidJUnit4.java:101)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:384)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2145)
----- end exception -----
09-13 00:06:24.875 17222-17238/com.mycompany.appname I/TestRunner: finished: testCrypto(com.mycompany.appname.crypto.CryptoTest)

现在最大的问题是:我的实现是否有错误,或者是框架错误,应该报告,以防止其他人无法对特定字节长度的数据进行解密和加密?

顺便说一句:我使用这样的缓冲 de 和加密解决了这个问题(AesGcmCrypto 中的交换方法)

private static final int CIPHER_CHUCK_SIZE = 64 * 1024;
@Override
public byte[] encrypt(byte[] message) throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance(AES_MODE);
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey());
GCMParameterSpec parameterSpec = cipher.getParameters().getParameterSpec(GCMParameterSpec.class);
int outLen = cipher.getOutputSize(message.length);

ByteArrayOutputStream bout = new ByteArrayOutputStream();
try {
for (int i = 0; i < message.length; i += CIPHER_CHUCK_SIZE) {
int len = Math.min(CIPHER_CHUCK_SIZE, message.length - i);
bout.write(cipher.update(message, i, len));
}
bout.write(cipher.doFinal());
} catch (IOException e) {
e.printStackTrace();
throw new GeneralSecurityException(e);
}

byte[] cryptedBytes = bout.toByteArray();
if (outLen != cryptedBytes.length)
throw new GeneralSecurityException("cryptedBytes too small");

byte[] iv = parameterSpec.getIV();
byte[] encryptedSecretKey = getEncryptedSecretKey();
return ByteBuffer.allocate(iv.length + encryptedSecretKey.length + cryptedBytes.length)
.put(iv)
.put(encryptedSecretKey)
.put(cryptedBytes)
.array();
}

@Override
public byte[] decrypt(byte[] bytes) throws GeneralSecurityException {
ByteBuffer buffer = ByteBuffer.wrap(bytes);
byte[] iv = new byte[IV_SIZE];
buffer.get(iv);

//skip aes key bytes
byte[] irrelevant = new byte[AES_KEY_SIZE * 8];
buffer.get(irrelevant);

byte[] encryptedMessage = new byte[bytes.length - IV_SIZE - irrelevant.length];
buffer.get(encryptedMessage);

Cipher cipher = Cipher.getInstance(AES_MODE);
GCMParameterSpec parameterSpec = new GCMParameterSpec(AES_TAG_LEN, iv);
cipher.init(Cipher.DECRYPT_MODE, getSecretKey(), parameterSpec);

ByteArrayOutputStream bout = new ByteArrayOutputStream();
try {
for (int i = 0; i < encryptedMessage.length; i += CIPHER_CHUCK_SIZE) {
int len = Math.min(CIPHER_CHUCK_SIZE, encryptedMessage.length - i);
cipher.update(encryptedMessage, i, len);
}
bout.write(cipher.doFinal());
} catch (IOException e) {
e.printStackTrace();
throw new GeneralSecurityException(e);
}

byte[] decryptedMessage = bout.toByteArray();
return decryptedMessage;
}

由于这个修复,我坚信它一定是一个框架错误。如果有高深的加密知识的人能启发我,我将非常高兴。

最佳答案

我还没有找到根本问题。我只能说,这似乎不是错误!

我已经简化了去和加密如下:

package com.dermalog.votercheck.crypto;

import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;


public class SimpleCrypto {

private final SecretKey mSecretKey;

public SimpleCrypto(SecretKey secretKey){
mSecretKey = secretKey;
}

public byte[] encrypt(byte[] data) throws GeneralSecurityException {
Cipher aes = Cipher.getInstance("AES/GCM/NoPadding");
aes.init(Cipher.ENCRYPT_MODE, mSecretKey);
GCMParameterSpec parameterSpec = aes.getParameters().getParameterSpec(GCMParameterSpec.class);
byte[] encrypted = aes.doFinal(data);
if (encrypted.length != aes.getOutputSize(data.length)){
throw new GeneralSecurityException("Encrypted Output Size does not match cipher.getOutputSize");
}
return ByteBuffer.allocate(12 + encrypted.length).put(parameterSpec.getIV()).put(encrypted).array();
}

public byte[] decrypt(byte[] encryptedData) throws GeneralSecurityException{

ByteBuffer buffer = ByteBuffer.wrap(encryptedData);
byte[] iv = new byte[12];
buffer.get(iv);
GCMParameterSpec parameterSpec = new GCMParameterSpec(128, iv);

Cipher aes = Cipher.getInstance("AES/GCM/NoPadding");
aes.init(Cipher.DECRYPT_MODE, mSecretKey, parameterSpec);

byte[] encryptedMessage = new byte[encryptedData.length - 12];
buffer.get(encryptedMessage);
return aes.doFinal(encryptedMessage);
}
}

并像这样(成功地)测试了它:

@Test
public void testSimpleCrypto() throws GeneralSecurityException {
SecureRandom secureRandom = new SecureRandom();
Random random = new Random();
byte[] keyBytes = new byte[32];
secureRandom.nextBytes(keyBytes);

SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES");
SimpleCrypto crypto = new SimpleCrypto(secretKey);

String test = "SecretData";

byte[] encrypted = crypto.encrypt(test.getBytes(StandardCharsets.UTF_8));
byte[] decrypted = crypto.decrypt(encrypted);
Assert.assertEquals(new String(decrypted, StandardCharsets.UTF_8), test);

byte[] randomData = new byte[81920];
random.nextBytes(randomData);

encrypted = crypto.encrypt(randomData);
decrypted = crypto.decrypt(encrypted);
Assert.assertArrayEquals(randomData, decrypted);

randomData = new byte[131073];
random.nextBytes(randomData);

encrypted = crypto.encrypt(randomData);
decrypted = crypto.decrypt(encrypted);
Assert.assertArrayEquals(randomData, decrypted);

for (int i = 1024 * 20; i < 1024 * 300; i+= 1024) {
randomData = new byte[i];
random.nextBytes(randomData);

encrypted = crypto.encrypt(randomData);
decrypted = crypto.decrypt(encrypted);
Assert.assertArrayEquals(randomData, decrypted);
}
}

所以这个 bug 一定是在我这边的实现(虽然我不知道为什么我实现的修复在那时起作用)

只是想写一个跟进。

顺便说一句:如果有人想获得赏金,只需回答即可。名誉扫地就太可惜了^^

关于Android AES/GCM/NoPadding 特定长度输入字节的错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52300583/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com