我想尝试加密文件并使用以下堆栈溢出响应。然而,在测试初始化向量时,我发现它只影响前 16 个字节。
当我将一个空的 iv 传递给解密密码(前 16 个字节除外)时,数据被意外解密。 [我假设图书馆没有坏,而且我做的事情不正确;但这是一个可怕的想法,其他人可能在同一条船上却没有意识到这一点。]
例子:
Initial bytes ..... 2222222222222222222222222222222222222222222222222222
Encrypted bytes ... b35b3945cdcd08e2f8a65b353ff754c32a48d9624e16b616d432
Decrypted bytes ... 3c4154f7f33a2edbded5e5af5d3d39b422222222222222222222
Run Code Online (Sandbox Code Playgroud)
问:为什么整个解密没有失败?
推测:我想我可以通过一次迭代 16 个字节的数据并通过对先前加密的 16 个字节块进行散列来更新每轮的 iv 来进行加密。然而,这似乎是我期望图书馆做的繁忙的工作。我本来希望提出实施指南的专家会提到它。但我只是抓住了这里的稻草。据我所知,也许安全社区只担心第一个区块的黑客攻击。
注意:刚才我发现了一个 5.5 年前的堆栈溢出帖子,它发现了同样的问题;不幸的是,它仍然没有回应。
package test;
import java.security.AlgorithmParameters;
import java.security.spec.KeySpec;
import java.util.Formatter;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
/*
* Issue: Using "AES/CBC/PKCS5Padding" encryption, the Initialization Vector
* appears to only affect the first block?!?
*
* Example Output
* iv …Run Code Online (Sandbox Code Playgroud) 背景:
我一直在研究一种Android应用程序,它将数据存储在本地数据库中作为我的宠物项目.最近,我决定要密码保护应用程序并加密数据库.现在,我知道在运行中加密数据库的复杂性并且(考虑到我的应用程序的预期使用模式)决定只加密整个数据库文件而不是尝试存储加密的列值等.到目前为止,我已经实现了一个系统,该系统将在每次应用程序启动时或每当用户导航离开我的活动时提示输入密码(以说明用户按下主页键并且应用程序未及时被杀死).
目前,我正在尝试确定如何对密码进行哈希处理以及在何处存储密码.鉴于所有内容都必须存储在设备上,我基本上将密码哈希和盐视为已经泄密,因为任何花了10分钟阅读的人都可以根据给定的设备访问我的数据库/首选项.
鉴于上述假设,我已经开发了我认为仍应提供非常强大的安全性的东西.我希望从社区获得一些反馈,看看我的解决方案是否可行或是否有更好的方法.
我的想法是在应用程序的第一次运行时生成10个不同的随机盐值.这些值将与应用程序首选项(而不是数据库)中的实际最终密码哈希一起存储.请注意,只有一个密码,它用于用户身份验证和数据库解密.每当提出质询时,密码将按如下方式进行散列:
我认为这个过程进行5次迭代会产生5 ^ 10个不同的盐组合,并且应该使任何类型的彩虹攻击几乎不可能.一旦验证了最终散列,就可以使用它来解密数据库.
现在,我意识到这听起来像一个简单的手机应用程序的矫枉过正.它是.但是,这是我的宠物项目,为什么不呢?
问题:
那么,在那段文字之后,这种方法是否合理还是有更好的方法?我认为,有了这个,最薄弱的环节是内存中的攻击还是我弄错了?任何反馈都非常感谢.
先感谢您.
-干杯
可以通过此代码生成AES密钥
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
Run Code Online (Sandbox Code Playgroud)
但
如果我有一个"非常可靠"的方法来生成随机数,我可以用这种方式使用它
SecureRandom rnd = new SecureRandom();
byte[] key = new byte[16];
rnd.nextBytes(key);
Run Code Online (Sandbox Code Playgroud)
这种方法可靠获得的关键是什么?
或者它只能由一些SPECIAL算法生成
http://www.hanewin.net/encrypt/aes/aes-test.htm
如果您访问此网站并输入以下内容:
"Key In Hex": 00000000000000000000000000123456
"Plain Text in Hex": 00000000000000000000000000000000
Run Code Online (Sandbox Code Playgroud)
然后单击"加密"按钮,您将看到十六进制中的密文是:
3fa9f2a6e4c2b440fb6f676076a8ba04
Run Code Online (Sandbox Code Playgroud)
有没有一个Java程序可以做到这一点(即是否有一个AES库,它将输入上面的"十六进制输入",上面的"纯文本输入十六进制"并生成十六进制的密文?)?
我将不胜感激任何建议或指向Java示例代码的链接.
在这个问题及其答案之后,我正在创建一个应用程序,该应用程序给出一个密码字符串,将转换明文并将其密文、生成的盐和初始化向量存储在文本文件中。
在以下代码中:
public String decrypt(CryptGroup cp) throws Exception {
String plaintext = null;
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(password, cp.getSalt(), ITERATIONS, KEY_SIZE);
SecretKey secretKey = factory.generateSecret(spec);
SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(cp.getIv()));
plaintext = new String(cipher.doFinal(cp.getCipher()), "UTF-8");
return plaintext;
}
public CryptGroup encrypt(String plainText) throws Exception {
byte[] salt = generateSalt();
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(password, salt, ITERATIONS, KEY_SIZE);
SecretKey secretKey = factory.generateSecret(spec); …Run Code Online (Sandbox Code Playgroud) 我首先要描述我遇到的问题,然后给出一些我想要做的背景.最后,我将粘贴一些相关的代码片段.
我正在尝试使用/sf/answers/69468941/中指定的方法实现密钥加密/解密.如果我按原样使用该示例,它可以工作(虽然我确实注意到我需要重新实例化Cipher该类,否则解密会产生垃圾).但是,在我的实现中,我得到以下异常:
java.security.InvalidKeyException: Wrong algorithm: AES or Rijndael required
at com.sun.crypto.provider.AESCrypt.init(AESCrypt.java:77)
at com.sun.crypto.provider.CipherBlockChaining.init(CipherBlockChaining.java:91)
at com.sun.crypto.provider.CipherCore.init(CipherCore.java:469)
at com.sun.crypto.provider.AESCipher.engineInit(AESCipher.java:217)
at javax.crypto.Cipher.implInit(Cipher.java:790)
at javax.crypto.Cipher.chooseProvider(Cipher.java:848)
at javax.crypto.Cipher.init(Cipher.java:1347)
at javax.crypto.Cipher.init(Cipher.java:1281)
at securitytest.SecurityManager.getCipher(SecurityManager.java:175)
at securitytest.SecurityManager.decryptSecretKey(SecurityManager.java:379)
at securitytest.SecurityManager.<init>(SecurityManager.java:82)
at securitytest.Test.main(Test.java:44)
Run Code Online (Sandbox Code Playgroud)
为了击败这个显而易见的问题,是的,我使用相同的算法:实际上,我分配AES/CBC/PKCS5Padding了一个常量并使用它来实例化Cipher加密和解密的类.我也尝试仅使用AES实例化Cipher进行解密,但这也无效.
我想要做的是使用AES/CBC/PKCS5Padding密码保护密钥.我生成一个随机盐和初始化矢量.在加密密钥后,我将初始化向量(字节数组)附加到加密值(也是一个字节数组,创建一个新数组).然后,我在Base64中对此值进行编码,并将其与salt一起存储在Sqlite数据库中(为简单起见,我将其存储为以逗号分隔的值字符串).但是当我尝试解密时,我得到了上述异常.我可以在调用加密方法之后直接验证,并且直接在解密方法之前验证,以下值完全相同(当转换为Base64时,我可以将其打印出来):
我已经尝试了Java 6和7:两者都给出了相同的结果.我还排除了无限强度管辖权政策文件的问题.事实上,如果我用另一种算法替换"AES"并相应地调整盐的长度(例如"Blowfish",IV长度为8,产生java.security.InvalidKeyException: Wrong algorithm: Blowfish required),我会得到类似的错误.
谷歌无法帮助我解决这个问题.如果有人能够对此有所了解,我将非常感激.
这里有一些代码片段(我的道歉,它有点粗糙):
private static final int INIT_VECTOR_LENGTH = 16;
private static final int PRIVATE_KEY_LENGTH = 128;
private static final int SALT_LENGTH = …Run Code Online (Sandbox Code Playgroud) 除了DES,3DES和AES加密技术之外,我还实施了PBE.与其他三个相比,我需要PBE的一些优势.当我在互联网上搜索时,我只是发现了缺点.帮我弄清楚使用PBE的一些优点?
我有一段时间没有下载弹簧.我正在调查gradle,但似乎还没有它,所以我想用java,Spring 4和ant创建一个新的spring框架项目.我似乎无法找到下载Spring 4二进制文件的地方.
他们只是在公共汽车下踢蚂蚁开发人员吗?
我使用此代码在Java和Android中加密和解密一些字符串,在每个系统中我得到不同的值.
我正在使用的代码来自http://www.androidsnippets.com/encryptdecrypt-strings(我不会粘贴它,因为它非常大).
例如在Android中加密"aa"我得到这个:1C6BD31C57F42ACFD0EDD2DD5B7A92CA
与Java中的种子具有相同密钥的完全相同的字符串我得到:61FAD1203B7AC92AD9345771AA273DA5
任何的想法?
提前致谢!
java ×10
encryption ×7
aes ×4
android ×2
cryptography ×1
encoding ×1
security ×1
spring ×1
spring-4 ×1
sqlite ×1