【问题标题】:How do I encrypt/decrypt a string with another string as a password?如何使用另一个字符串作为密码加密/解密一个字符串?
【发布时间】:2011-12-07 10:42:20
【问题描述】:

我正在制作一个简单的程序,它接受在文本框中输入的文本,并接受另一个文本框中的密码,然后对其进行某种简单的加密并将其保存到文件中。之后,用户应该能够再次打开文件并提供用于加密它的密码,它应该会吐出原始文本。

现在我正在接受字符串。将其分成一个字符数组,然后对密码执行相同的操作。之后,我获取密码,将所有这些字符转换为整数,找到所有字符的平均值,并将其用作原始文本中字符的偏移量。有点像:

textChars[1]= (char)((int)textChars[1]+offset);

然后我可以对加密的字符串做相反的事情:

encryptedChars[1]= (char)((int)encryptedChars[1]-offset);

问题是字符在不同平台上具有不同的值,因此有时偏移量会将 char 变成一些疯狂的数字(如负值),这只会将 char 变成问号。

我查看了标准 Java API 中的加密库,但如果密钥是每次启动程序时随机生成的,我对它的工作原理感到困惑。

我需要的是两个看起来像 String encrypt(String text,String Password) 的函数,它会吐出用密码加密的文本作为解密它的密钥,而 String decrypt(String encryptedText, String Password) 会吐出原始文本(如果密码是垃圾,则为乱码)

非常感谢任何帮助,这实际上只是一个个人项目,所以我不需要任何花哨的加密方法。

【问题讨论】:

标签: java string cryptography encryption


【解决方案1】:

您真正需要的是对称加密,即算法使用相同的密钥来加密和解密数据。支持对称加密的算法有很多,如 DES、AES。

看看这个例子:http://www.java2s.com/Code/Java/Security/EncryptionanddecryptionwithAESECBPKCS7Padding.htm

在上面的例子中,替换

byte[] keyBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
    0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 };

byte[] keyBytes = yourPassword.getBytes();

它使用 bouncycastle 库,可以说是最好的加密库。

【讨论】:

  • 这似乎是目前为止最有希望的解决方案,我去试试看。
  • @Shahzeb java2s有什么问题?我个人认为网站上的示例是一个好的开始,而不是从头开始。
  • 您不应该直接使用密码作为密钥 - 您应该始终首先使用密钥延伸。
  • 这是完全不安全的。您需要使用 PBKDF2 之类的东西从密码中导出密钥。否则,您将陷入密码的熵非常低的困境,人们很容易猜到。
  • 而且你不想使用欧洲央行。至少使用 CBC 或者更好的 AEAD 模式。
【解决方案2】:

您正在尝试重新发明*。除非你是为了好玩,否则我建议使用 AES 之类的东西。如果你只是用谷歌搜索“Java 中的 AES”,你会发现很多例子。

如果您这样做是为了好玩并且想要一些简单的实现,请查看ROT13

以下是 Java 中的 AES 示例:

private static final String ALGORITHM = "AES";
private static final byte[] keyValue = 
    new byte[] { 'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y' };

 public String encrypt(String valueToEnc) throws Exception {
    Key key = generateKey();
    Cipher c = Cipher.getInstance(ALGORITHM);
    c.init(Cipher.ENCRYPT_MODE, key);
    byte[] encValue = c.doFinal(valueToEnc.getBytes());
    String encryptedValue = new BASE64Encoder().encode(encValue);
    return encryptedValue;
}

public String decrypt(String encryptedValue) throws Exception {
    Key key = generateKey();
    Cipher c = Cipher.getInstance(ALGORITHM);
    c.init(Cipher.DECRYPT_MODE, key);
    byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedValue);
    byte[] decValue = c.doFinal(decordedValue);
    String decryptedValue = new String(decValue);
    return decryptedValue;
}

private static Key generateKey() throws Exception {
    Key key = new SecretKeySpec(keyValue, ALGORITHM);
    return key;
}

您可能希望改进此代码。

【讨论】:

  • 好的,我使用了您提供的代码,但改用了 DES,因为我不知道 AES 需要多少个字符,而且我真的不关心强保护。感谢您的帮助!
  • 大多数加密算法适用于字节,而不是字符和字符串。根据 AES 规范,密钥应该是 128、192 或 256 位。要将字符串用作键,请查看:*.com/questions/3451670/…
最近更新 更多