RIJNDAEL 256 CBC encryption with IV in java - java

I have a reference of PHP code that does Rijndael encryption. I want convert it to java code, I tried few examples but none of them worked for me.
Here is the php code:
$initialisationVector = hash("sha256", utf8_encode($myiv), TRUE);
$key = hash("sha256", utf8_encode($mykey), TRUE);
$encryptedValue = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256,$encryptKey, utf8_encode($mydata), MCRYPT_MODE_CBC, $initialisationVector));
Here is my java code that throws: Key length not 128/160/192/224/256 bits
public static String encrypt() throws Exception{
String myiv = "somevalue";
String mykey = "somevalue";
String mydata = "somevalue";
String new_text = "";
RijndaelEngine rijndael = new RijndaelEngine(256);
CBCBlockCipher cbc_rijndael = new CBCBlockCipher(rijndael);
ZeroBytePadding c = new ZeroBytePadding();
PaddedBufferedBlockCipher pbbc = new PaddedBufferedBlockCipher(cbc_rijndael, c);
byte[] iv_byte = sha256(myiv);
byte[] givenKey = sha256(mykey);
CipherParameters keyWithIV = new ParametersWithIV(new KeyParameter(givenKey), iv_byte);
pbbc.init(true, keyWithIV);
byte[] plaintext = mydata.getBytes(Charset.forName("UTF-8"));
byte[] ciphertext = new byte[pbbc.getOutputSize(plaintext.length)];
int offset = 0;
offset += pbbc.processBytes(plaintext, 0, plaintext.length, ciphertext, offset);
offset += pbbc.doFinal(ciphertext, offset);
new_text = new String(new Base64().encode(ciphertext), Charset.forName("UTF-8"));
System.out.println(new_text);
return new_text;
}
public static byte[] sha256(String input) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] messageDigest = md.digest(input.getBytes(Charset.forName("UTF-8")));
return messageDigest;
}
I am not really good with cryptography. Thanks in advance!

The error message is clear: "initialisation vector must be the same length as block size". You are specifiying a 256-bit (32-byte) block size, verify that iv_byte is 32-bytes.
There are a few problems:
For the IV get the bytes from the hash, pass the bytes to the encryption function, BigInteger has no place in that.
sha256(appId) provides a 256-bit key, just use it.
The following are not needed, the result of sha256 is 256-bits:
final int keysize = 256;
byte[] keyData = new byte[keysize];
System.arraycopy(givenKey, 0, keyData, 0, Math.min(givenKey.length, keyData.length));
sha256(appId) provides a 256-bit key, just use it.
The following are not needed:
final int keysize = 256;
byte[] keyData = new byte[keysize];
System.arraycopy(givenKey, 0, keyData, 0, Math.min(givenKey.length, keyData.length));
mcrypt "MCRYPT_RIJNDAEL_256" is specifying a 256-bit block size which means it is not AES, "MCRYPT_RIJNDAEL_128" is AES which should be used.
mcrypt uses non-standard null padding, that needs to be accommodated.
Using a SHA-256 hash is not sufficiently secure, use a password derivation function such as PBKDF2.

Related

Encrypting Java then Decrypting C# AES256 Encryption with HMACSHA256, Padding is invalid

I'm currently running into an issue where our decryption portion of our C# site is having trouble with the padding with the encrypted string from java. The .Net code throws this error "Padding is invalid and cannot be removed". The _signKey and _encKey are both 64 bytes.
public String encryptString(String plainText) {
byte[] ciphertext;
byte[] iv = new byte[16];
byte[] plainBytes = plainText.getBytes(StandardCharsets.UTF_8);
String _signKey = "****************************************************************";
String _encKey = "****************************************************************";
try {
Mac sha256 = Mac.getInstance("HmacSHA256");
SecretKeySpec shaKS = new SecretKeySpec(_signKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
sha256.init(shaKS);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecureRandom randomSecureRandom = SecureRandom.getInstance("SHA1PRNG");
iv = new byte[cipher.getBlockSize()];
randomSecureRandom.nextBytes(iv);
IvParameterSpec ivParams = new IvParameterSpec(iv);
byte[] sessionKey = sha256.doFinal((_encKey + iv).getBytes(StandardCharsets.UTF_8));
// Perform Encryption
SecretKeySpec eks = new SecretKeySpec(sessionKey, "AES");
cipher.init(Cipher.ENCRYPT_MODE, eks, ivParams);
ciphertext = cipher.doFinal(plainBytes);
System.out.println("ciphertext= " + new String(ciphertext));
// Perform HMAC using SHA-256 on ciphertext
SecretKeySpec hks = new SecretKeySpec(_signKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(hks);
ByteArrayOutputStream outputStream2 = new ByteArrayOutputStream();
outputStream2.write(iv);
outputStream2.write(ciphertext);
outputStream2.flush();
outputStream2.write(mac.doFinal(outputStream2.toByteArray()));
return Base64.encodeBase64String(outputStream2.toByteArray());
} catch (Exception e) {
e.printStackTrace();
}
return plainText;
}
Does does encrypt the string properly as far as I can tell. We cannot change any code on the .Net side to decrypt this because this is being used today.
public static string DecryptString(string ciphertext)
{
using (HMACSHA256 sha256 = new HMACSHA256(Encoding.UTF8.GetBytes(_signKey)))
{
// Convert message to bytes
byte[] encBytes = Convert.FromBase64String(ciphertext);
// Get arrays for comparing HMAC tags
byte[] sentTag = new byte[sha256.HashSize / 8];
byte[] calcTag = sha256.ComputeHash(encBytes, 0, (encBytes.Length - sentTag.Length));
// If message length is too small return null
if (encBytes.Length < sentTag.Length + _ivLength) { return null; }
// Copy tag from end of encrypted message
Array.Copy(encBytes, (encBytes.Length - sentTag.Length), sentTag, 0, sentTag.Length);
// Compare tags with constant time comparison, return null if no match
int compare = 0;
for (int i = 0; i < sentTag.Length; i++) { compare |= sentTag[i] ^ calcTag[i]; }
if (compare != 0) { return null; }
using (AesCryptoServiceProvider csp = new AesCryptoServiceProvider())
{
// Set parameters
csp.BlockSize = _blockBits;
csp.KeySize = _keyBits;
csp.Mode = CipherMode.CBC;
csp.Padding = PaddingMode.PKCS7;
// Copy init vector from message
var iv = new byte[_ivLength];
Array.Copy(encBytes, 0, iv, 0, iv.Length);
// Derive session key
byte[] sessionKey = sha256.ComputeHash(Encoding.UTF8.GetBytes(_encKey + iv));
// Decrypt message
using (ICryptoTransform decrypt = csp.CreateDecryptor(sessionKey, iv))
{
return Encoding.UTF8.GetString(decrypt.TransformFinalBlock(encBytes, iv.Length, encBytes.Length - iv.Length - sentTag.Length));
}
}
}
}
If there is anything that sticks out it would be appreciated for the reply.
I didn't read all your code, but this line in Java:
byte[] sessionKey = sha256.doFinal((_encKey + iv).getBytes(StandardCharsets.UTF_8));
does nothing useful or sensible. The "+" operator does string concatenation, but iv is a byte[], not a String. So java uses iv.toString(), which simply returns a String containing something like [B#1188e820 which is meaningless in this context.
Refer four java code and DotNet code:
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); //Java
csp.Padding = PaddingMode.PKCS7; //.Net
You are essentially using different padding, that is the probable source of error; however, there is an alternate view, Refer this great post and this for general fundamentals on padding
The cipher suites supported by deafult Oracle JVM implementation are here
If you notice it does not have 'AES/CBC/PKCS7Padding', a PKCS#7 padding implementation is available in sun.security package, refer this, otherwise you could use Bouncy Castle packages. It would be recommendable to use Bouncy Castle as com.sun package are generally considered unsupported.

Migrate openssl to java

I need to migrate a crypto package from C++/openssl to pure java implementation. However, I am having some issues that I don't know how to solve.
Below is a C++ list that outlines a decryption scheme that I am currently trying to migrate.
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
// set master key
AES_KEY master_key;
const int AES128_KEY_SIZE = 16;
unsigned char* master_secret = "averysecretmastersecret";
AES_set_encrypt_key(master_secret, AES128_KEY_SIZE * 8 , &master_key);
// Base64 decode; encryptedInput is the original input text
// b64_output consists of two parts: a leading salt (16 bytes) and the following actual data
char* b64_output = base64Decode(encryptedInput); // base64Decode(const char* encodedText) -> char* decodedText
// prepare salt
const char SALT_LEN = 16; // first byte is reserved. Actually only use 15 bytes = 120 bit
unsigned char salt[SALT_LEN];
memcpy(salt, b64_output, SALT_LEN); // read salt
// generate key
const int AES128_KEY_SIZE = 16;
unsigned char key[AES128_KEY_SIZE];
salt[0] = 1; //
AES_ecb_encrypt(salt, key, &master_key, AES_ENCRYPT);
// generate iv
const int AES128_IV_SIZE = 16;
unsigned char iv[AES128_IV_SIZE];
salt[0] = 2; // ensure that key and iv are different
AES_ecb_encrypt(salt, iv, &master_key, AES_ENCRYPT);
// initialize cipher context
EVP_CIPHER_CTX *de;
de = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(de);
EVP_DecryptInit_ex(de, EVP_aes_128_cbc(), NULL, key, iv)
aes_decrypt(b64_output + SALT_LEN, length - SALT_LEN);
// plaintext is a buffer to contain the output
int plaintext_size = DEFAULT_BUFFER_SIZE;
char *plaintext = (char*)malloc(plaintext_size);
int aes_decrypt(const char *ciphertext, int len)
{
int p_len = len, f_len = 0;
// allocate an extra cipher block size of memory because padding is ON
// #define AES_BLOCK_SIZE 16
if(p_len + AES_BLOCK_SIZE > plaintext_size) {
ASSERT_CALL(enlarge_buffer(plaintext, plaintext_size, p_len + AES_BLOCK_SIZE), "enlarge plaintext buffer failed");
}
ASSERT_OPENSSL( EVP_DecryptInit_ex(de, NULL, NULL, NULL, NULL), "sets up decode context failed");
ASSERT_OPENSSL( EVP_DecryptUpdate(de, (unsigned char*)plaintext, &p_len, (unsigned char*)ciphertext, len), "decrypt failed");
EVP_DecryptFinal_ex(de, (unsigned char*)plaintext+p_len, &f_len);
return EY_SUCCESS;
}
EVP_CIPHER_CTX_free(de);
dec_result = std::string(plaintext);
Below is a java code list that I currently have (not working, of course) to reproduce above C++ logic:
String encrypted = "AtUKTnCF18kFTJIycg/RXKJ82IVCtaa+eKNVl8FhT0k+wvpc+cBIs5jb/QlLRMf4";
String secret = "averysecretmastersecret";
int SALT_LEN = 16;
String keyAlgorithm = "AES";
String ECB_TRANSFORM = "AES/ECB/NoPadding";
String CBC_TRANSFORM = "AES/CBC/NoPadding";
byte[] bytesOfSecret = Arrays.copyOf(secret.getBytes(), 16);
Key key =new SecretKeySpec(bytesOfSecret, keyAlgorithm);
Cipher ecbCipher = Cipher.getInstance(ECB_TRANSFORM);
Cipher cbcCipher = Cipher.getInstance(CBC_TRANSFORM);
// decode
byte[] decoded = Base64.getDecoder().decode(encrypted);
byte[] salt = Arrays.copyOf(decoded, SALT_LEN);
byte[] data = Arrays.copyOfRange(decoded, SALT_LEN, decoded.length);
// get iv
salt[0] = 2;
ecbCipher.init(Cipher.ENCRYPT_MODE, key);
byte[] iv = ecbCipher.doFinal(salt);
iv = Arrays.copyOf(iv, 16);
AlgorithmParameterSpec parameterSpec = new IvParameterSpec(iv);
cbcCipher.init(Cipher.DECRYPT_MODE, key, parameterSpec);
byte[] bytes = cbcCipher.doFinal(data);
String decrypted = new String(bytes);
System.out.println(decrypted);
There are a couple places that I don't know how to map from C++ to java right now. First, in the C++ code, it uses a salt to generate a key and an iv, which are subsequently used to initialize EVP cipher context as in EVP_DecryptInit_ex(de, EVP_aes_128_cbc(), NULL, key, iv). I don't know the equivalent operation in java.
Second, there is no direct mentioning in the C++ code whether padding is used. I tried both NoPadding and PKCS5Padding, but not sure which one is the right one.
So, how can I reproduce the C++ logic in java? Is there any example out there?
update
I also tried BouncyCastle. It is still not working. Below is my code:
int SALT_LEN = 16;
String encrypted = "AtUKTnCF18kFTJIycg/RXKJ82IVCtaa+eKNVl8FhT0k+wvpc+cBIs5jb/QlLRMf4";
String password = "averysecretmastersecret";
// decode
byte[] decoded = Base64.getDecoder().decode(encrypted);
byte[] salt = Arrays.copyOf(decoded, SALT_LEN);
byte[] data = Arrays.copyOfRange(decoded, SALT_LEN, decoded.length);
BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new AESEngine()));
PBEParametersGenerator generator = new OpenSSLPBEParametersGenerator();
byte[] bytesOfSecret = PBEParametersGenerator.PKCS5PasswordToBytes(password.toCharArray());
generator.init(bytesOfSecret, salt, 1);
ParametersWithIV parametersWithIV = (ParametersWithIV) generator.generateDerivedParameters(128, 128);
// for decryption
cipher.init(false, parametersWithIV);
byte[] decrypted = new byte[cipher.getOutputSize(data.length)];
System.out.println("expected decrypted size = " + decrypted.length); // prints ... size = 32
int processedBytes = cipher.processBytes(data, 0, data.length, decrypted, 0);
System.out.println("processed bytes = " + processedBytes); // prints ... bytes = 16
cipher.doFinal(decrypted, processedBytes); // Line 59, run into exception
String output = new String(decrypted);
System.out.println(output);
Line 59, as marked above, gives this exception:
org.bouncycastle.crypto.InvalidCipherTextException: pad block corrupted
at org.bouncycastle.crypto.paddings.PKCS7Padding.padCount(Unknown Source)
at org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher.doFinal(Unknown Source)
...
This is an example of java AES encryption i hope this helps
String key = "HkJHBKJBvffdbv";
String IV= "qjfghftrsbdghzir";
String theMessageToCifer ="your message";
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES");
IvParameterSpec ivSpec = new IvParameterSpec(IV.getBytes());
try{
//specify your mode
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec,ivSpec);
encrypted = cipher.doFinal(theMessageToCifer.getBytes());
bytesEncoded = Base64.encode(encrypted);
System.out.println(" base64 code " +bytesEncoded);
System.out.println("encrypted string: " +encrypted);
// decryption
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec,ivSpec);
byte[] original = cipher.doFinal(encrypted);
String originalString = new String(original);
System.out.println("Original string: " + originalString );
}catch (Exception e){
e.printStackTrace();
}

How to use three keys with triple des(3des) in Java

I found a link in stackoverflow here use-3des-encryption-decryption-in-java,but in fact the method uses only two parameter:HG58YZ3CR9" and the "IvParameterSpec iv = new IvParameterSpec(new byte[8]);"
But the most strong option of triple des could use three different key to encrypt the message.So how to do that? I find a mehond in Cipher, which use "SecureRandom" as another parameter.So is this the right way?
The first method code is below:
import java.security.MessageDigest;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class TripleDESTest {
public static void main(String[] args) throws Exception {
String text = "kyle boon";
byte[] codedtext = new TripleDESTest().encrypt(text);
String decodedtext = new TripleDESTest().decrypt(codedtext);
System.out.println(codedtext); // this is a byte array, you'll just see a reference to an array
System.out.println(decodedtext); // This correctly shows "kyle boon"
}
public byte[] encrypt(String message) throws Exception {
final MessageDigest md = MessageDigest.getInstance("SHA-1");
final byte[] digestOfPassword = md.digest("HG58YZ3CR9"
.getBytes("utf-8"));
final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
for (int j = 0, k = 16; j < 8;) {
keyBytes[k++] = keyBytes[j++];
}
final SecretKey key = new SecretKeySpec(keyBytes, "DESede");
final IvParameterSpec iv = new IvParameterSpec(new byte[8]);
final Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
final byte[] plainTextBytes = message.getBytes("utf-8");
final byte[] cipherText = cipher.doFinal(plainTextBytes);
// final String encodedCipherText = new sun.misc.BASE64Encoder()
// .encode(cipherText);
return cipherText;
}
public String decrypt(byte[] message) throws Exception {
final MessageDigest md = MessageDigest.getInstance("SHA-1");
final byte[] digestOfPassword = md.digest("HG58YZ3CR9"
.getBytes("utf-8"));
final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
for (int j = 0, k = 16; j < 8;) {
keyBytes[k++] = keyBytes[j++];
}
final SecretKey key = new SecretKeySpec(keyBytes, "DESede");
final IvParameterSpec iv = new IvParameterSpec(new byte[8]);
final Cipher decipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
decipher.init(Cipher.DECRYPT_MODE, key, iv);
// final byte[] encData = new
// sun.misc.BASE64Decoder().decodeBuffer(message);
final byte[] plainText = decipher.doFinal(message);
return new String(plainText, "UTF-8");
}
}
As per this document, simply pass the cipher a key that is 168 bits long.
Keysize must be equal to 112 or 168.
A keysize of 112 will generate a Triple DES key with 2 intermediate keys, and a keysize of 168 will generate a Triple DES key with 3 intermediate keys.
Your code seems to do something questionable to make up for the fact that the output of MD5 is only 128 bits long.
Copy-pasting cryptographic code off the internet will not produce secure applications. Using a static IV compromises several reasons why CBC mode is better than ECB. If you are using a static key, you should probably consider generating random bytes using a secure random number generator instead of deriving the key from a short ASCII string. Also, there is absolutely no reason to use Triple DES instead of AES in new applications.
In principle, the for-next loop to generate the DES ABA key does seem correct. Note that you can provide DESede with a 16 byte key from Java 7 onwards, which amounts to the same thing.
That said, the code you've shown leaves a lot to be desired:
I is not secure:
the key is not generated by a Password Based Key Derivation Function (PBKDF) using the (password?) string
the key is composed of two keys instead of three (using a triple DES or TDEA with an ABA key)
the IV is set to all zero's instead of being randomized
the "password" string is too short
Furthermore the following code mistakes can be seen:
using new sun.misc.BASE64Encoder() which is in the Sun proprietary packages (which can be removed or changed during any upgrade of the runtime)
throwing Exception for platform exceptions and runtime exceptions (not being able to decrypt is handled the same way as not being able to instantiate the Cipher)
requesting 24 bytes instead of 16 within the Arrays.copyOf() call (which seems to return 24 SHA-1 output while there are only 20 bytes)
To generate a 3DES 24 byte (168 bits used) DES ABC key from a password (like) String you should use PBKDF-2. Adding an authentication tag is also very important if man-in-the-middle attacks or padding oracle apply. It would be much secure and much more practical to upgrade to AES if you can control the algorithms being used as well.

3DES - Decrypt encrypted text (by JAVA) in C#

Here is the situation:
The encrypted text is done in JAVA (which we have no JAVA background at all)
The method is 3DES
The padded is PKCS#5
Base 64
The decryption will be in C#, and here is the code:
public static string DecryptString(string Message, string Passphrase)
{
byte[] Results;
UTF8Encoding UTF8 = new UTF8Encoding();
MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase));
TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();
TDESAlgorithm.Key = TDESKey;
TDESAlgorithm.Mode = CipherMode.ECB;
TDESAlgorithm.Padding = PaddingMode.PKCS7;
byte[] DataToDecrypt = Convert.FromBase64String(Message);
try
{
ICryptoTransform Decryptor = TDESAlgorithm.CreateDecryptor();
Results = Decryptor.TransformFinalBlock(DataToDecrypt, 0, DataToDecrypt.Length);
}
finally
{
TDESAlgorithm.Clear();
HashProvider.Clear();
}
return UTF8.GetString(Results);
}
However, when tried to decrypt, got the error message: BAD DATA
Where am I missing here?
Thanks in advance.
Added, and here's how the encryption works:
<cffunction name="getToken" returntype="String" output="false">
<cfscript>
plainText = getPlainText();
rawSecretKey = CreateObject("java","sun.misc.BASE64Decoder").decodeBuffer(variables.encryptionKey);
secretKeySpec = CreateObject("java","javax.crypto.spec.SecretKeySpec").init(rawSecretKey,"DESEDE");
cipher = CreateObject("java","javax.crypto.Cipher").getInstance("DESEDE");
cipher.init(Cipher.ENCRYPT_MODE, secretkeySpec);
encrypted = cipher.doFinal(plainText.getBytes()); // a byte array (a binary in CF)
return URLEncodedFormat(ToString(ToBase64(encrypted)));
</cfscript>
</cffunction>
Update:
This issue has been resolved. The problem was that the key needed to be converted from Base64.
The answer:
Instead of:
byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase));
Do this:
byte[] TDESKey = Convert.FromBase64String(Passphrase);
That solves this issue.

Equivalent to CryptoStream .NET in Java?

I have an encrypted string in visual basic. NET 2008, the functions to encrypt and decrypt are the following:
Imports System.Security.Cryptography
Public Shared Function Encriptar(ByVal strValor As String) As String
Dim strEncrKey As String = "key12345"
Dim byKey() As Byte = {}
Dim IV() As Byte = {&H12, &H34, &H56, &H78, &H90, &HAB, &HCD, &HEF}
Try
byKey = System.Text.Encoding.UTF8.GetBytes(strEncrKey)
Dim des As New DESCryptoServiceProvider
Dim inputByteArray() As Byte = Encoding.UTF8.GetBytes(strValor)
Dim ms As New MemoryStream
Dim cs As New CryptoStream(ms, des.CreateEncryptor(byKey, IV), CryptoStreamMode.Write)
cs.Write(inputByteArray, 0, inputByteArray.Length)
cs.FlushFinalBlock()
Return Convert.ToBase64String(ms.ToArray())
Catch ex As Exception
Return ""
End Try
End Function
Public Shared Function Desencriptar(ByVal strValor As String) As String
Dim sDecrKey As String = "key12345"
Dim byKey() As Byte = {}
Dim IV() As Byte = {&H12, &H34, &H56, &H78, &H90, &HAB, &HCD, &HEF}
Dim inputByteArray(strValor.Length) As Byte
Try
byKey = System.Text.Encoding.UTF8.GetBytes(sDecrKey)
Dim des As New DESCryptoServiceProvider
If Trim(strValor).Length = 0 Then
Throw New Exception("Password No debe estar en Blanco")
End If
inputByteArray = Convert.FromBase64String(strValor)
Dim ms As New MemoryStream
Dim cs As New CryptoStream(ms, des.CreateDecryptor(byKey, IV), CryptoStreamMode.Write)
cs.Write(inputByteArray, 0, inputByteArray.Length)
cs.FlushFinalBlock()
Dim encoding As System.Text.Encoding = System.Text.Encoding.UTF8
Return encoding.GetString(ms.ToArray(), 0, ms.ToArray.Count)
Catch ex As Exception
Return ""
End Try
End Function
for example the word "android" encrypted with this function gives me the result "B3xogi/Qfsc="
now I need to decrypt the string "B3xogi/Qfsc=" it from java, by the same key, which is "key12345", and the result should be "android"...anyone know how to do this?
Thanks in advance.
Using Apache Commons Codec for hex and base64 encoding/decoding, you can use the following code:
KeySpec ks = new DESKeySpec("key12345".getBytes("UTF-8"));
SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(ks);
IvParameterSpec iv = new IvParameterSpec(
Hex.decodeHex("1234567890ABCDEF".toCharArray()));
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key, iv);
byte[] decoded = cipher.doFinal(Base64.decodeBase64("B3xogi/Qfsc="));
System.out.println("Decoded: " + new String(decoded, "UTF-8"));
You're using DES encryption.
Here is an example on how to encrypt and decrypt with DES.
The main point is to create a SecretKey, a Cipher using it, and decrypt your String with it.
Mmmh...
I found another article that may best suit your question, because it uses IVBytes :)
public String encryptText(String cipherText) throws Exception {
String plainKey = "key12345";
String plainIV = "1234567890ABCDEF";
KeySpec ks = new DESKeySpec(plainKey.getBytes(encodingType));
SecretKey key = SecretKeyFactory.getInstance(keyDes).generateSecret(ks);
IvParameterSpec iv = new IvParameterSpec(
org.apache.commons.codec.binary.Hex.decodeHex(plainIV.toCharArray()));
Cipher cipher = Cipher.getInstance(encryptAlgo);
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
byte[] decoded = cipher.doFinal(cipherText.getBytes(encodingType));
return new Base64().encodeToString(decoded);
}
The closest Java classes to .NET's CryptoStream class are the CipherInputStream and CipherOutputStream classes.

Categories