在将此标记为重复之前,请理解我在 stackoverflow 上找不到任何关于河豚的有用信息。我正在尝试使用 Android Studio 使用河豚加密和解密字符串。我的加密似乎有效。但是当我尝试解密所述字符串时,它明显更短并且用字符编码。我对加密非常陌生,非常感谢任何帮助。
加密
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Encryption {
private String algorithm = "Blowfish/CBC/PKCS5Padding";
private SecretKeySpec keySpec;
private Cipher cipher;
public void setupForEncryption(String keyString) throws java.security.GeneralSecurityException, UnsupportedEncodingException {
byte[] keyData = keyString.getBytes();
keySpec = new SecretKeySpec(keyString.getBytes("UTF-8"), "Blowfish");
cipher = Cipher.getInstance(algorithm);
}
public SecretKeySpec getSecretKey() {
return keySpec;
}
public boolean checkForKeySpec() {
if (keySpec != null) {
return true;
}
return false;
}
public String encryptString(String inputString) throws java.security.GeneralSecurityException, UnsupportedEncodingException {
IvParameterSpec ivSpec = new IvParameterSpec(keySpec.getEncoded());
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(),ivSpec);
byte[] encryptedBytes = cipher.doFinal(inputString.getBytes("UTF-8"));
return new String(encryptedBytes);
}
解密
import android.util.Base64;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Decryption {
private SecretKeySpec keySpec;
private String algorithm = "Blowfish/CBC/PKCS5Padding";
private Cipher cipher;
public void setupForDecryption(String key) throws NoSuchPaddingException, NoSuchAlgorithmException, UnsupportedEncodingException {
byte[] keyData = key.getBytes();
keySpec = new SecretKeySpec(key.getBytes("UTF-8"), "Blowfish");
cipher = Cipher.getInstance(algorithm);
}
public boolean checkForKeySpec() {
if(keySpec != null){
return true;
}
return false;
}
public SecretKeySpec getSecretKey() {
return keySpec;
}
public String decryptString(String inputString) throws InvalidKeyException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, UnsupportedEncodingException {
IvParameterSpec ivSpec = new IvParameterSpec(keySpec.getEncoded());
cipher.init(Cipher.DECRYPT_MODE, getSecretKey(),ivSpec);
byte[] decryptedBytes = Base64.decode(inputString,0);
String decrypted = new String(decryptedBytes);
return decrypted;
}
}
最佳答案
你在加密期间这样做:
return new String(encryptedBytes);
其中 encryptedBytes
可以包含任何字节值。通过强制将这些字节转换为字符串,您实际上是在丢弃那些在默认编码中不可打印的字节。
此外,在解密过程中,您忘记了解密 (cipher.doFinal(inputString.getBytes("UTF-8"))
)。我只看到Base64.decode
,这是一种编码,不是加密。
如果要发送字符串,则需要使用 Base64 或 Hex 等编码将字节数组编码为可打印的字符串。
从字节转换为字符串时始终使用特定的编码 bytes.getBytes("UTF-8")
并返回 new String(str, "UTF-8")
。否则,当默认字符集更改时,您可能会遇到设备之间的不兼容问题。
总是在 CBC 模式下使用随机 IV。它提供语义安全。 IV 不必是 secret 的,因此您可以简单地将它与密文一起发送并在解密过程中使用它。简单地将其作为密文的前缀是很常见的。
关于java - Blowfish 加密问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36002834/