如何用另一个字符串作为密码加密/解密字符串?

7
我正在制作一个简单的程序,它可以接收用户在文本框中输入的文本和密码,然后对其进行一些简单的加密并将其保存到文件中。之后,用户应该能够再次打开文件并提供用于加密的密码,从而得到原始文本。
目前,我正在将字符串分成字符数组,然后对密码做同样的操作。之后,我将密码转换为整数,找到所有整数的平均值,并将其用作原始文本中字符的偏移量。有点像这样:
textChars[1]= (char)((int)textChars[1]+offset);

那么我可以对加密字符串进行反转:

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

问题在于不同平台上字符的值是不同的,因此有时偏移量会使字符变成一些奇怪的数字(如负值),这将把字符变成问号。
我查看了标准Java API中的加密库,但我感到困惑,因为如果密钥每次启动程序时都是随机生成的,那么它的工作原理是什么。
我需要两个函数,看起来像String encrypt(String text,String Password),它使用密码作为密钥加密文本以解密它,和String decrypt(String encryptedText, String Password),它可以输出原始文本(或垃圾文本如果密码是无用的)
非常感谢任何帮助,这只是一个个人项目,因此我不需要任何高端的加密方法。

哦,是的,MD5是一种方法,我懒得读整篇文章 :) - Shahzeb
可能是Java 256位AES加密的重复问题。 - Tim Bender
你不应该存储加密密码。你的使用场景是什么?你是想验证用户是否知道他们的密码,还是想创建一个密码保险库?如果是后者,并且你对Java加密感到困惑,那就不要这样做。如果是前者,则不要加密密码,而是存储密码的哈希值,例如SHA-256哈希值,然后在以后给出密码时再次进行哈希并与您存储的哈希进行比较。确保也存储盐。也许在你最终制作出会让你陷入麻烦的东西之前,你应该多了解一下所有这些工作原理。 - Steve Owens
2个回答

12

你正在试图重复发明轮子。除非你只是出于兴趣,否则我建议使用类似 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;
}

你可能想要改进这段代码。


1
好的,我使用了您提供的代码,但改用了DES,因为我不知道AES需要多少个字符,而且我真的不在乎强大的保护。感谢您的帮助! - RangerMauve
大多数加密算法都是基于字节而非字符和字符串的。根据AES规范,密钥应为128、192或256位。如果要使用字符串作为密钥,请参考以下链接:https://dev59.com/pXA75IYBdhLWcg3wJFcL - Akshay

6
您需要的是对称加密,即使用相同的密钥来加密和解密数据的算法。有许多支持对称加密的算法,例如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库,这是目前最好的密码学库之一。

这似乎是目前最有希望的解决方案,我会去尝试一下。 - RangerMauve
@Shahzeb,Java2s有什么问题吗?我个人认为该网站上的示例是一个很好的起点,而不是从头开始。 - Manish
1
你不应该直接使用密码作为密钥 - 你应该先进行密钥延伸。 - Nick Johnson
2
这是完全不安全的。你需要使用像PBKDF2这样的东西来从密码中派生出一个密钥。否则,你将被困在密码非常非常低的熵值中,有人可以轻易地猜测出来。 - imichaelmiers
而且你不想使用 ECB。至少要使用 CBC 或者更好的 AEAD 模式。 - QuantumMechanic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接