我正在尝试用java编写一个简单的密码管理器.我想使用AES 256位加密使用存储的密码加密文件.此外,我希望用户能够使用密码解密文件.当在线阅读其他帖子时,他们几乎都强调单纯使用密码作为密钥是不安全的,他们提到使用随机盐来增加安全性.但我不明白在生成密钥时如何使用随机盐.如果我从用户的密码和随机盐创建密钥,那么当他们尝试解密他们的文件时,我怎么知道盐是什么?这让我完全糊涂了.
目前,我在每一步使用恒定盐通过几个不同的哈希值运行密码.这是否足够安全,或者我错过了什么?任何有关如何从密码安全生成密钥的帮助将不胜感激!提前致谢.
我正在编写一个解密存储在文件中的文本的Android应用程序.我用了以下代码 -
public class SimpleCrypto {
public static String encrypt(String seed, String cleartext)
throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] result = encrypt(rawKey, cleartext.getBytes());
return toHex(result);
}
public static String decrypt(String seed, String encrypted)
throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] enc = toByte(encrypted);
byte[] result = decrypt(rawKey, enc);
return new String(result);
}
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
sr.setSeed(seed);
kgen.init(128, sr); // 192 and 256 bits …Run Code Online (Sandbox Code Playgroud) 编辑:::问题中的代码有效,但一旦图像在相机中拍摄,返回活动大约需要10秒钟.我放弃了这种方法,并使用Facebook的隐藏库来加密和解密图像.链接到Facebook的解决方案:Facebook隐藏 - 图像加密和解密
我已经查看了很多示例,但仍然无法找到一种正确的加密和解密方法.当我在互联网上使用一些随机代码时,我认为我弄错了,但在解码时,我得到了BadPadding异常.
所以,我正在尝试解决它.我按照下面的问题,正如大多数人在SO上所建议的那样(但这段代码显示了如何加密字符串).有人可以帮助我加密和解密图像吗?问题中的代码是否适用于图像?
链接到问题:Java 256位AES密码加密
这是我到目前为止所做的事情:
//用于存储iv和密码的全局arraylist
static ArrayList<byte[]> ivandcipher = new ArrayList<byte[]>();
Run Code Online (Sandbox Code Playgroud)
//生成密钥
public static SecretKey generateKey() throws NoSuchAlgorithmException {
char[] password = { 'a', 'b', 'c', 'd', 'e' };
byte[] salt = { 1, 2, 3, 4, 5 };
SecretKeyFactory factory = SecretKeyFactory
.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(password, salt, 65536, 256);
SecretKey tmp = null;
try {
tmp = factory.generateSecret(spec);
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
yourKey = new SecretKeySpec(tmp.getEncoded(), "AES");
return …Run Code Online (Sandbox Code Playgroud) 我执行以下操作以基于KeyStore中的用户密码存储SecretKey:
// load KeyStore
static byte[] salt = // for learning purposes
{ (byte) 0xc7, (byte) 0x73, (byte) 0x21, (byte) 0x8c,
(byte) 0x7e, (byte) 0xc8, (byte) 0xee, (byte) 0x99 };
String alias = "aeskey";
char[] password = "password".toCharArray();
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(password, salt, 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES/CBC/PKCS5Padding");
Entry aesentry = new KeyStore.SecretKeyEntry(secret);
store.setEntry(alias, aesentry, protParam);
Run Code Online (Sandbox Code Playgroud)
现在我可以从KeyStore获取SecretKey:
KeyStore.SecretKeyEntry e = (SecretKeyEntry) store.getEntry("aeskey", protParam);
secret = e.getSecretKey();
Run Code Online (Sandbox Code Playgroud)
如何从SecretKey获取初始密码?
我需要将下面的C#代码翻译成Java,但是,我找不到任何与C#的Rfc2898DerivedBytes和Rijndael相当的Java.
private static string Encrypt(string sData, string sEncryptionKey)
{
string str = null;
string str2;
try
{
Rfc2898DeriveBytes bytes = new Rfc2898DeriveBytes(sEncryptionKey, 8);
Rijndael rijndael = Rijndael.Create();
rijndael.IV = bytes.GetBytes(rijndael.BlockSize / 8);
rijndael.Key = bytes.GetBytes(rijndael.KeySize / 8);
byte[] buffer = Encoding.Unicode.GetBytes(sData);
using (MemoryStream stream = new MemoryStream())
{
using (CryptoStream stream2 = new CryptoStream(stream, rijndael.CreateEncryptor(), CryptoStreamMode.Write))
{
stream.Write(bytes.Salt, 0, bytes.Salt.Length);
stream2.Write(buffer, 0, buffer.Length);
stream2.Close();
str = Convert.ToBase64String(stream.ToArray());
str2 = str;
}
}
}
catch (Exception exception)
{
System.out.println(exception.getMessage());
}
return …Run Code Online (Sandbox Code Playgroud) java ×5
encryption ×4
android ×2
aes ×1
cryptography ×1
cryptostream ×1
javax.crypto ×1
keystore ×1
rfc2898 ×1
rijndael ×1