我现在已经阅读了几个地方,基本上建议不要在源代码中存储密码,我理解原因。
我有两个应用程序:一个用于加密,一个用于解密。数据被加密到服务器上的文件;此文件在客户端的计算机上下载并解密,然后由专有应用程序(不是我的)处理。数据是敏感的,(理想情况下)只能由处理应用程序访问。 目前我正在使用对称密钥算法,因为数据足够大。密码作为字符串硬编码到源代码中 - 我知道,有几个原因很糟糕。
我想知道的是存储密码的最佳方法是什么?我的想法是使用非对称密钥算法,例如RSA,只是为了密码,但无法解决如何做到这一点,如果它在我的场景中甚至有意义。我不想引入另一个文件进行分发。我不太了解反编译,但我认为在客户端应用程序中实现PBKD会带来同样的问题。正如你所知,密码学对我来说是新的,并且使用这个伟大的论坛。
答案 0 :(得分:0)
请不要在源文件中使用对称密钥。您可以在不引入其他文件的情况下使用RSA。与对称密钥相反,如果可以保证源文件的完整性,则可以在源代码中对公钥进行硬编码,而不会出现任何安全问题。然后,如果有人设法改变它,解密将不起作用或正在进行中间人(MITM)攻击(你不会知道它)。
CAVEATS
好的,不管怎样,让我们深入研究。示例代码完全使用JDK 8编写。
首先,生成密钥对。这需要一次或每次需要旋转时完成:
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
KeyPair keyPair = kpg.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
byte[] pubEnc = publicKey.getEncoded();
byte[] privKeyEnc = privateKey.getEncoded();
System.out.println(Base64.getEncoder().encodeToString(pubEnc));
System.out.println(Base64.getEncoder().encodeToString(privKeyEnc));
假设公钥是(这些是我生成的实际密钥,不使用这些密钥):
private static final String PUBLIC_KEY_BASE64 =
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCGue
5TCdPJt08w7crbvWjfcSUy/xXjzjjjjPDP7D8PNSnn
CUeNcGWsR/Pd3eoBjmrAy/4Rl8JlHylRry8pX7Zpcz
iQB8wWQdpkSoArjeu4taeFn/45+eg4J5mzmIzFG9F5
wF7N+SeSvtq3E3Q0mtJRRZZJYgNkFmeDuOQjljJVZw
IDAQAB";
,私钥是:
private static final String PRIVATE_KEY_BASE64 =
"MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAg
EAAoGBAIa57lMJ08m3TzDtytu9aN9xJTL/FePOOOOM
8M/sPw81KecJR41wZaxH893d6gGOasDL/hGXwmUfKV
GvLylftmlzOJAHzBZB2mRKgCuN67i1p4Wf/jn56Dgn
mbOYjMUb0XnAXs35J5K+2rcTdDSa0lFFlkliA2QWZ4
O45COWMlVnAgMBAAECgYBAWTIRi1ISuHEkh48qoS8j
+eCwmNGVuvvFA55JUSdVVikrZm08iwCk5sD9qW6JS8
KFT2mMcZWxws5za171PffbeHoIFaNI5n5OXJa4meZA
cgl4ae5su89BjvfzDF2gsnBHwLpgsT0aVdIDQ5BGtL
WzRwZCogY6lZhBOQZAaNFYIQJBALr2+kT+pkSlxrrR
tMxK7WL+hNO7qOIl/CTBuAa6/zTtoEjFMFQBY//jH+
6iabHDfKpaFwh6ynZTXZsb7qIKOM8CQQC4eRAH1VEo
iofZNnX3VjiI5mLtV8rc8Jg+wznN+WFnwdNoLK8y9t
EcuKxg3neIJAM70D6l0IhBfza1QAqQh4/pAkA5vyLZ
wJV2SoWxGihvmQztMJOyGho1j2nrqHHAkm1U2bhSAa
XFrJBIbsxkFoHyx+BvdVf75IE4PtOAnwX7wpB9AkBQ
7CKBHS2N+D8hpQdYqcUBIPdyoFmIVC6lEaTw2x3Ekz
027KsqUyVmUQilMdIDsbCNc4uX14N+H90S43X+8sjJ
AkAKsvRbZ0Au9JytSRKSB7vYl37283zHoQ5jyYUE7x
g7C6nWSl1GEa6khZ47hFAj9C2bdLJ6GtjTleFsVCsR
LUoG";
由于格式原因,上面的代码行换行。
假设args[0]
为"attack at dawn!"
,您的客户端看起来像这样:
public static void main(String[] args) throws Exception {
byte[] pubKey = Base64.getDecoder().decode(PUBLIC_KEY_BASE64);
PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(pubKey));
Cipher cipher = Cipher.getInstance("RSA");
Cipher.init(Cipher.ENCRYPT_MODE, publicKey);
String encryptedData = Base64.getEncoder().encodeToString(cipher.doFinal(args[0].getBytes("UTF-8")));
System.out.println("Encrypted data is: " + encryptedData);
}
输出:加密数据是: cDoPpQYc6qibrBl5jdENcV + g6HslQDlo9potca5rQxecnxR3Bd / e1T0njqUMACl7x7AG3foGxqZyyUIMrOVXcnw / ux7BgQcg + RDZhSVFQAd5kUGI96pw8WtDVo1N1 + WEfaaPhK9CpwUKUxtwR0t27n + W0vhFCqNTEGhofLt8u9o =
服务器:
public static void main(String[] args) throws Exception {
byte[] privKey = Base64.getDecoder().decode(PRIVATE_KEY_BASE64);
PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(privKey));
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] encryptedData = Base64.getDecoder().decode(args[0]);
byte[] decryptedData = cipher.doFinal(encryptedData);
System.out.println("Decrypted message was: " + new String(decryptedData, "UTF-8"));
}
输出:解密的信息是:黎明时袭击!
JDK的RSA实现的一个很酷的事情是它使用来自PKCS#1的最佳非对称加密填充(OAEP),其效果是甚至相同的消息看起来与每次加密不同。
与之前的评论者提到的一样,如果没有全面了解,可能还有其他安全问题需要解决。但是对于它的价值,我认为这种方法比使用对称密钥更好,对称密钥仍然可以用于这种加密方案。然后你会得到所谓的混合密码系统,但有些API可以帮你做到这一点。
答案 1 :(得分:-2)
不是将明文密码存储在源中并检查,而是可以将加密密码存储在源中(硬编码)。
然后用户可以输入密码,代码对密码进行加密,并将加密结果与存储的加密值进行比较,以查看密码是否匹配。输入的密码(不是加密密码)然后用于加密/解密数据。
使用的加密应该努力将加密密码反转为明文密码很难/不可能。
示例:
This is my password1
(当前位于来源中的密码)。9845735b525fa70b2651975022a44be268af1d4defadba9ab2a0301e0579534c
。9845735b525fa70b2651975022a44be268af1d4defadba9ab2a0301e0579534c
This is my password1
对数据进行加密/解密。 黑客获取您的源并可以访问哈希9845735b525fa70b2651975022a44be268af1d4defadba9ab2a0301e0579534c
和您使用的算法。但他需要This is my password1
密码来解密数据。他可以反向或暴力破解哈希,但需要花费精力和时间。
人们可以使用种子等,但是为了保密它们也是同样的问题。
它可能不是最安全的,我不是专家,但它比在源中拥有This is my password1
更好。