如何使用密码解码字符串



我有一个密码,需要在网络中传输。因此,为了安全起见,我从发送端进行了编码,并在接收端进行了解码。

但我的朋友仍然能够在网络上破解密码,因为他知道我是如何编码密码字符串的。

这是我的代码

package org;
import java.util.Base64;
public class EncodingString {

public static void main(String[] args){
String  str = "I'm Encoding then decoding";
byte[]   bytesEncoded = Base64.getEncoder().encode(str.getBytes());
System.out.println(bytesEncoded);
String EncodedPassword = new String(bytesEncoded);
System.out.println("ecncoded value is " + EncodedPassword);
byte[] valueDecoded= Base64.getDecoder().decode(bytesEncoded);
System.out.println(valueDecoded);
String DecodedPassword = new String(valueDecoded);
System.out.println("Decoded value is " + DecodedPassword);

}
}

我想知道,有没有可能我可以在我编码的字符串上加上某种密码,这样我想解码的人就可以使用相同的密码?

这可能有助于您首先了解编码加密之间的区别。编码描述了一种用于表示信息的协议。您使用了base64,它将二进制信息编码为ASCII字符的子集。

加密是您想要的。加密算法使用密钥(您的"密码",有额外的要求)来操作数据,这样在没有密钥的情况下检索数据在计算上是困难的(读起来:实际上是不可能的)。

看看下面的摘录,它演示了如何在GCM模式下使用AES来安全地加密一些数据:

// The plaintext to encrypt, and the password we want to use.
String plaintext = "Hello, World!";
String password = "WizardsAreCool";
// Parameters for PBKDF2/AES.  Using a higher iteration count 
// is better in production.
int iterationCount = 25000;
int keySize = 128;
int tagSize = 128;
int saltSize = 16;
int nonceSize = 12;
// We generate a random salt for PBKDF2.
SecureRandom rng = new SecureRandom();
byte[] salt = new byte[saltSize];
rng.nextBytes(salt);
// We derive a 128-bit key using PBKDF2 from the password,
// as AES-128 expects a 128-bit key.  We also use SHA256 instead 
// of SHA1 for the underlying hash.
PBEKeySpec pwSpec = new PBEKeySpec(password.toCharArray(), salt, iterationCount, keySize);
SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
byte[] key = keyFac.generateSecret(pwSpec).getEncoded();
// We convert the plaintext to binary and generate a 12-byte nonce for 
// GCM mode.
byte[] rawData = plaintext.getBytes(StandardCharsets.UTF_8);
byte[] nonce = new byte[nonceSize];
rng.nextBytes(nonce);
// We define the cipher.
Cipher aesGcm = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec gcmSpec = new GCMParameterSpec(tagSize, nonce);
aesGcm.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), gcmSpec);
// We get the resulting ciphertext.
byte[] encResult = aesGcm.doFinal(rawData);
// We produce the final result by prepending the PBKDF2 salt and 
// the nonce.
byte[] result = new byte[saltSize + nonceSize + encResult.length];
System.arraycopy(salt, 0, result, 0, saltSize);
System.arraycopy(nonce, 0, result, saltSize, nonceSize);
System.arraycopy(encResult, 0, result, saltSize + nonceSize, encResult.length);
// Print the result as base64.
byte[] b64Result = Base64.getEncoder().encode(result);
System.out.println(new String(b64Result));
// Sample Output
// C100zs91Ku/TbQw4Mgw7e95didsA1Vj5oHGeMitohnRaUGIB08+T6uESro4P2Gf7q/7moMbWTTNT

与您的原始代码相比,上面的代码中有很多内容,所以我将尽我所能进行解释。我们使用的加密算法AES需要一个长度为128、192或256位的密钥。由于法律原因,Java禁止使用密钥大小不是128位的AES,因此我们被迫在这里使用128位密钥。

因为我们要使用的密码("WizardsAreCool")的长度不是128位(它实际上是14个UTF8字符长,所以是112位),所以我们使用PBKDF2,这是一个密钥派生函数,从我们的密码中派生一个128位长的密钥(因此keySize是128)。

PBKDF2在这里接受了一些参数,包括密码字符串、salt(当使用PBKDF2作为密钥派生函数时,这并不那么重要,但我们仍然应用了良好的实践,并使其随机,这是我们应该的),以及迭代计数,它决定了底层哈希应用于密码的次数。

AES还需要一些参数。最重要的是钥匙。它还需要一个nonce(因为我们处于GCM模式),它也应该是随机的。nonce用于从密码中生成加密的比特流,然后将其与我们的明文进行异或。

总而言之,上面的示例适合生产使用,并且是完全安全的。

最新更新