- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我写了一个类,用于对任意数据进行解密和加密。
它是这样工作的:因为 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/
我只想使用这 3 种模式从 openSSL 测试 AES: key 长度为 128,192 和 256,但我的解密文本与我的输入不同,我不知道为什么。此外,当我传递一个巨大的输入长度(比如说 1024
最近我终于(在 stackoverflow 的用户@WhozCraig 的帮助下)开始在 CBC 模式下使用 AES。现在,我想做完全相同的事情,但使用 AES IGE。我查看了 openssl-1.
网络设备已经配置了 snmpv3 用户,使用 AES192 作为隐私协议(protocol)。但是当执行以下命令时 snmpwalk -v3 -l authPriv -u user -a SHA -A
我在 c# 中使用 AES 算法进行加密和解密。我使用 AesCryptoServiceProvider 类进行加密和解密。 这是我在代码中的设置 AesCryptoServiceProvider r
我正在尝试使用具有不同 key 大小的 openssl 的 AES_decrypt 函数来解密密文。我能够成功解密 key 大小 = 128 的消息。这是我的代码 mydecrypt.c #inclu
如何在 AES-128、AES-192 和 AES-256 之间切换。我目前的实现仅使用 AES-128 Cipher cipher = Cipher.getInstance("AES/CBC/NoP
我的问题是我想在一个线图上叠加一个散点图,这两个图的颜色随着一个变量而变化。我只想保留一种颜色的图例。如果我使用 scale_colour_discrete(guide = "none") 它们都将消
我想用 C# 编写一个可以打开 KeePass 的程序1.x kdb 文件。我下载了源代码并尝试移植密码数据库读取功能。数据库内容已加密。加密 key 通过以下方式获得: 用户输入密码; 计算密码的
我只想将ruby代码迁移到Java 这是我的 ruby 代码 require 'openssl' require 'base64' key = '7c54367a45b37a192abc2cd7f45
我正在使用 AES 的 PyCrypto 实现,并且我正在尝试使用 24 字节 key 加密一些文本(24 字节)。 aes_ecb = AES.new('\x00'*24, AES.MODE_ECB
有人比较这些加密算法的优缺点吗? 最佳答案 使用 AES。 更多详细信息: DES 是七十年代的旧“数据加密标准”。它的 key 大小对于适当的安全性而言太短(56 个有效位;这可以被暴力破解,如 m
我在 iOS 中加密一个 NSString,编码和解码都很好: NSString *stringtoEncrypt = @"This string is to be encrypted"; NSStr
我正在尝试使用 nVidia CUDA 在 CTR 模式下实现 AES-256。我已经成功地为 key 扩展编写了 CPU 代码,现在我需要实现实际的 AES-256 算法。根据维基百科,我见过一些代
我正在 Contiki OS 中研究 AES 安全性。我有 AES 库,它支持两种类型的加密/解密: 即时 固定键 在即时中,当我使用 key 加密数据时,会生成新 key 和加密数据。这个新生成的
关于 AES 有很多问题,但我有以下问题。我目前正在使用以下 AES 实现来加密数据 byte [] PRFkey = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
有没有人一起比较这些加密算法的优缺点? 最佳答案 使用 AES。 更多细节: DES 是七十年代的旧“数据加密标准”。它的 key 大小对于适当的安全性来说太短了(56 位有效位;这可以被强制执行,正
我的团队需要开发一种解决方案,以在用 Java 编写的 Android 应用程序的上下文中加密二进制数据(存储为 byte[])。加密后的数据将通过多种方式传输和存储,在此过程中不排除出现数据损坏的情
我在客户端使用 CryptoJS AES 算法加密文本,我在服务器端用 java 解密它,但出现异常。 JS代码: var encrypted = CryptoJS.AES.encrypt("Mess
我之所以问这个问题,是因为 2 天来我已经阅读了很多关于加密 AES 加密的帖子,就在我以为我明白了的时候,我意识到我根本没有明白。 这篇文章是最接近我的问题的,我有完全相同的问题但没有得到解答: C
我想知道 AES 加密后的数据大小,这样我就可以避免缓冲我的 AES 后数据(在磁盘或内存上)主要是为了知道大小。 我使用 128 位 AES 和 javax.crypto.Cipher 和 java
我是一名优秀的程序员,十分优秀!