问题
I'm working on a project built in pure php, i'm doing a rework on the login, but the users in the database are cipher in Rijndael-256, i've tried a lot of things and nothing seems to work, and i feel i'm so close with this code, but it doesn't work, and i'm really lost
private final String key = "...";
public String decrypt(String password, String cypherKey) {
try {
password = password.substring(0, password.lenght() - 1); // 1
byte[] passwordBytes = password.getBytes("UTF-8");
byte[] key = cypherKey.getBytes("UTF-8");
RijndaelEngine rijndaelEngine = new RijndaelEngine(256);
KeyParameter keyParam = new KeyParameter(key);
rijndaelEngine.init(false, keyParam); // 2
PaddedBufferedBlockCipher bufferedBlock = new PaddedBufferedBlockCipher(rijndaelEngine, new ZeroBytePadding());
byte[] decryptedBytes = new byte[bufferedBlock.getOutputSize(passwordBytes.length)];
int processed = bufferedBlock.processBytes(passwordBytes, 0, passwordBytes.length, decryptedBytes, 0);
return String.valueOf(bufferedBlock.doFinal(decryptedBytes, processed));
} catch (Exeption e) {
e.printStackTrace();
}
return ""; // I know this is awful but i was trying something and left this like that
}
*1) I don't know if this is right but all the encrypted passwords end with equals sign and i tested with an encryption tool and i don't think it's needed
2) False is decryption mode
Stack trace: org.bouncycastle.crypto.DataLengthException: last block incomplete in decryption
I'm working on this decryption for two weeks now, i'm really desperate :(
PHP code:
function fnEncrypt($sValue)
{
include("constants.php");
return trim(
base64_encode(
mcrypt_encrypt(
MCRYPT_RIJNDAEL_256,
$SecretKey, $sValue,
MCRYPT_MODE_ECB,
mcrypt_create_iv(
mcrypt_get_iv_size(
MCRYPT_RIJNDAEL_256,
MCRYPT_MODE_ECB
),
MCRYPT_RAND)
)
)
);
}
function fnDecrypt($sValue)
{
include("constants.php");
return trim(
mcrypt_decrypt(
MCRYPT_RIJNDAEL_256,
$sSecretKey,
base64_decode($sValue),
MCRYPT_MODE_ECB,
mcrypt_create_iv(
mcrypt_get_iv_size(
MCRYPT_RIJNDAEL_256,
MCRYPT_MODE_ECB
),
MCRYPT_RAND
)
)
);
}
回答1:
In the decrypt
-method, the ciphertext must first be Base64-decoded (1). In addition, the length of the decrypted text is not determined correctly (2a) and the length of the corresponding byte-array is not adjusted accordingly (2b). Finally, there is a problem in determining the UTF8-string from the byte-array (3). Modify the body of the decrypt
-method as follows:
//password = password.substring(0, password.lenght() - 1); // 1 // Remove
//byte[] passwordBytes = password.getBytes("UTF-8"); // Remove
byte[] passwordBytes = Base64.getDecoder().decode(password); // Base64-decode the ciphertext (1)
byte[] key = cypherKey.getBytes("UTF-8");
RijndaelEngine rijndaelEngine = new RijndaelEngine(256);
KeyParameter keyParam = new KeyParameter(key);
rijndaelEngine.init(false, keyParam); // 2
PaddedBufferedBlockCipher bufferedBlock = new PaddedBufferedBlockCipher(rijndaelEngine, new ZeroBytePadding());
byte[] decryptedBytes = new byte[bufferedBlock.getOutputSize(passwordBytes.length)];
int processed = bufferedBlock.processBytes(passwordBytes, 0, passwordBytes.length, decryptedBytes, 0);
processed += bufferedBlock.doFinal(decryptedBytes, processed); // Refresh the parameter containing the length of the decrypted data (2a)
decryptedBytes = Arrays.copyOfRange(decryptedBytes, 0, processed); // Reduce the byte-array accordingly (2b)
//return String.valueOf(bufferedBlock.doFinal(decryptedBytes, processed)); // Remove
return new String(decryptedBytes, "UTF-8"); // Create a UTF-8 string from the byte-array (3)
with the imports java.util.Base64
and org.bouncycastle.util.Arrays
.
Even though this is probably legacy code, two notes on security: Passwords should generally not be encrypted, but hashed. In addition, ECB is insecure.
回答2:
This was my solution:
/**
* Step 1: password and key are converted to bytes in order to be processed by the cypher.
*
* Step 2: a KeyParameter is created with the key bytes.
*
* Step 3: a PaddedBufferedBlockCipher statement is assigned with Rijndael 256 algorithm and ZeroBytePadding, this padder adds NULL byte padding to a block.
*
* Step 4: the bufferedBlockCipher is then initialized with parameters "true" meaning Encryption mode, and the KeyParameter.
* This initialization prepares the bufferedBlock with the parameters needed for encryption.
*
* Step 5: a variable "buffer" stores the length in bytes the output should have
*
* Step 6: the processed bytes are calculated and stored, buffer now stores the value of the password
*
* Step 7: the encryption is finalized, the plus equals sign ensures that the output is multiple of 32
*
* Step 8: the buffer and processedBytes are converted into an array of bytes and then a String
*
* @param password
*
* @return
*/
public String encrypt(String password) throws InvalidCipherTextException {
byte[] data = password.getBytes();
byte[] encryptionKey = key.getBytes();
KeyParameter keyParameter = new KeyParameter(encryptionKey);
PaddedBufferedBlockCipher bufferedBlockCipher = new PaddedBufferedBlockCipher(new RijndaelEngine(256), new ZeroBytePadding());
bufferedBlockCipher.init(true, keyParameter);
byte[] buffer = new byte[bufferedBlockCipher.getOutputSize(data.length)];
int processedBytes = bufferedBlockCipher.processBytes(data, 0, data.length, buffer, 0);
processedBytes += bufferedBlockCipher.doFinal(buffer, processedBytes);
byte[] result = Arrays.copyOfRange(buffer, 0, processedBytes);
String output = Base64.encodeBase64String(result);
return output;
}
来源:https://stackoverflow.com/questions/57965316/rijndael-256-encryption-with-java-bouncy-castle