I feel like I have tried everything to get java to PHP using AES; however, I have found that the keys are not the same after I hashed them. I have kept the salt as a string because I couldn't get it to work with an empty byte array; however, it hasn't changed anything. I heard somewhere that dividing the key length by 8 is needed in PHP, so that's why I have it.
I know the hash functions to check for matching works as I have tested it with a random string, and they match up.
JAVA:
public static void main(String[] args) {
SecretKey secret = generateSecret("PASSWORD");
System.out.println(hashString(new String(secret.getEncoded()));
}
public static SecretKey generateSecret(String password) throws Exception {
//byte[] salt = new byte[8];
byte[] salt = "SALT".getBytes("UTF-8");
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 65536, 256);
SecretKey secretKey = factory.generateSecret(keySpec);
return new SecretKeySpec(secretKey.getEncoded(), "AES");
}
public static String hashString(String request) throws Exception {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-512");
byte[] buffer = messageDigest.digest(request.getBytes());
StringBuffer sb = new StringBuffer(buffer.length * 2);
for (int i = 0; i < buffer.length; i++) {
int v = buffer[i] & 0xff;
if (v < 16) {
sb.append('0');
}
sb.append(Integer.toHexString(v));
}
return sb.toString().toUpperCase();
}
PHP:
$password = 'PASSWORD';
salt = 'SALT';//pack('nvc*', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
$bytes = derivateKey($password, $salt, 65536, 256);
echo hash('sha512', $bytes);
function derivateKey($password, $salt, $iterations, $keyLengthBits){
return hash_pbkdf2('sha512', $password, $salt, $iterations, $keyLengthBits/8, true);
}
Java returns with this hash:
9E6B73EA6FA176F8D0651AC4DA73F0CEBE603DA6B31A226443CABBB80EDF51BCE663F92945F5DC1C0B8F0098DDE61C3117CCEDFEB7DB4A959315DE635BC7F1BB
php returns with this hash:
135d49502ca99da44f3050f37e7ca0e8ca16c18a9b3120c95bb8cf45e97c0120053c51a3f134fbf38c4105186362086e9504a130dc3ad5633c9968f2b12c1ac6
Related
I am using a C# "encrypt" and need a Java "decrypt" method. I need help in java that i can't replicate C# decryption on java and it is not explicit Padding on C# , i don't know what use in java and my key size I think is different but I am not sure. I'm very confused.
know that i need change Java Policy , and did it ! and Change Key size JAVA to 32 bytes.
C#
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using Voa.Cross.Util.Extensions;
namespace Voa.Core.Safeties
{
public class Security
{
private readonly string _defaultKey = "sjkdhfjksdhf3444KDFK4nFLFGKdsnjcnj2cmkeKDIK484dmd999sksksksUUddUZ83k030394m49jdjPuWzRk8Zq2PfnpR3YrYWSq2AaUT6meeC3tr36nTVkuudKWbDyPjhUwbwXBzkUhSPKPpSRheR49em4qJWa6YHSCjKX3K93FEMnqXhYauXwjJwbHXfPWTSdxy6ebCBPyAfqk7Uz5nrRddVjZrxWNCMZYG3PbcvPWA34ekdkd454ldnvJKl";
private readonly int _divisionKey = 4;
private readonly byte[] _iv = new byte[16] {0x26, 0xdc, 0xff, 0x00, 0xad, 0xed, 0x7a, 0xee, 0xc5, 0xfe, 0x07, 0xaf, 0x4d, 0x08, 0x22, 0x3c};
private byte[] _key;
public Security() => _key = SHA256.Create().ComputeHash(Encoding.ASCII.GetBytes(_defaultKey));
public string Encrypt(string data, string key)
{
if (!string.IsNullOrEmpty(key))
{
CustomKey(key);
}
var encryptor = Aes.Create();
encryptor.Mode = CipherMode.CBC;
// Set key and IV
var aesKey = new byte[32];
Array.Copy(_key, 0, aesKey, 0, 32);
encryptor.Key = aesKey;
encryptor.IV = _iv;
var memoryStream = new MemoryStream();
var aesEncryptor = encryptor.CreateEncryptor();
var cryptoStream = new CryptoStream(memoryStream, aesEncryptor, CryptoStreamMode.Write);
var plainBytes = Encoding.ASCII.GetBytes(data);
cryptoStream.Write(plainBytes, 0, plainBytes.Length);
cryptoStream.FlushFinalBlock();
var cipherBytes = memoryStream.ToArray();
memoryStream.Close();
cryptoStream.Close();
var cipherText = Convert.ToBase64String(cipherBytes, 0, cipherBytes.Length);
return cipherText;
}
public string Decrypt(string data, string key)
{
if (!string.IsNullOrEmpty(key))
{
CustomKey(key);
}
var encryptor = Aes.Create();
encryptor.Mode = CipherMode.CBC;
var aesKey = new byte[32];
Array.Copy(_key, 0, aesKey, 0, 32);
encryptor.Key = aesKey;
encryptor.IV = _iv;
var memoryStream = new MemoryStream();
var aesDecryptor = encryptor.CreateDecryptor();
var cryptoStream = new CryptoStream(memoryStream, aesDecryptor, CryptoStreamMode.Write);
var plainText = string.Empty;
try
{
var cipherBytes = Convert.FromBase64String(data);
cryptoStream.Write(cipherBytes, 0, cipherBytes.Length);
cryptoStream.FlushFinalBlock();
var plainBytes = memoryStream.ToArray();
plainText = Encoding.ASCII.GetString(plainBytes, 0, plainBytes.Length);
}
finally
{
memoryStream.Close();
cryptoStream.Close();
}
return plainText;
}
private void CustomKey(string key)
{
var blockSize = key.Length / _divisionKey;
var splitKey = key.CutString(blockSize).ToList();
var splitDefaultKey = _defaultKey.CutString(blockSize).ToList();
var newKey = string.Concat(splitDefaultKey.Intertwine(splitKey).ToList());
_key = SHA256.Create().ComputeHash(Encoding.ASCII.GetBytes(newKey));
}
}
}
JAVA test...
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class SecurityAESEncryption {
private static final String _key = "sjkdhfjksdhf3444KDFK4nFLFGKdsnjcnj2cmkeKDIK484dmd999sksksksUUddUZ83k030394m49jdjPuWzRk8Zq2PfnpR3YrYWSq2AaUT6meeC3tr36nTVkuudKWbDyPjhUwbwXBzkUhSPKPpSRheR49em4qJWa6YHSCjKX3K93FEMnqXhYauXwjJwbHXfPWTSdxy6ebCBPyAfqk7Uz5nrRddVjZrxWNCMZYG3PbcvPWA34ekdkd454ldnvJKl";
private static final char[] initCharArray = new char[] {0x26, 0xdc, 0xff, 0x00, 0xad, 0xed, 0x7a, 0xee, 0xc5, 0xfe, 0x07, 0xaf, 0x4d, 0x08, 0x22, 0x3c};
private static final byte[] initVector = SecurityAESEncryption.charToByteArray(initCharArray);
//private static final String initArray = "26dcff00aded7aeec5fe07af4d08223c";
//private static final byte[] ivValue = SecurityAESEncryption.hexStringToByteArray(initArray);
//private static final byte[] key = DigestUtils.sha256(_key.getBytes(StandardCharsets.US_ASCII)).;
private static final byte[] key = SecurityAESEncryption.computeHash(_key);
public static String encrypt(String value) {
try {
System.out.println(key.length);
System.out.println(Base64.decodeBase64(key).length);
byte[] aesKey = new byte[32];
System.arraycopy(key, 0, aesKey, 0, 32);
SecretKeySpec skeySpec = new SecretKeySpec(aesKey, "AES");
IvParameterSpec iv = new IvParameterSpec(initVector);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(value.getBytes());
return Base64.encodeBase64String(encrypted);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static String decrypt(String encrypted) {
try {
byte[] encryptedBytes = Base64.decodeBase64(encrypted);
System.out.println(key.length);
System.out.println(Base64.decodeBase64(key).length);
byte[] aesKey = new byte[32];
System.arraycopy(key, 0, aesKey, 0, 32);
IvParameterSpec iv = new IvParameterSpec(initVector);
SecretKeySpec skeySpec = new SecretKeySpec(aesKey, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
//byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));
byte[] original = cipher.doFinal(encryptedBytes);
return new String(original,StandardCharsets.US_ASCII);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static byte[] charToByteArray(char[] x)
{
final byte[] res = new byte[x.length];
for (int i = 0; i < x.length; i++)
{
res[i] = (byte) x[i];
}
return res;
}
public static byte[] computeHash(String input) {
try {
// Static getInstance method is called with hashing SHA
MessageDigest md = MessageDigest.getInstance("SHA-256");
return md.digest(input.getBytes(StandardCharsets.US_ASCII));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
public static void main(String[] args) {
String originalString = "123456!##";
System.out.println("Original String to encrypt - " + originalString);
String encryptedString = encrypt(originalString);
System.out.println("Encrypted String - " + encryptedString);
String decryptedString = decrypt("Ci10C7ZjUPoEnitdh7QkEw==");
System.out.println("After decryption - " + decryptedString);
}
Your edited Java prog now successfully encrypts the string "123456!##" to this (Base64 encoded) string "LnZV0Vph+eUeJLT2Gst0kw==" using a String as input to a SHA-256 digest, so the real key used for en-/decryption is
(hex) "07c3491eaa6a6289ca91b7b0f290d60688538860b44753f1cf9617977985d2db".
Using this encoded string as input for your decrypt method returns the original string but when using the encoded/encrypted
string "Ci10C7ZjUPoEnitdh7QkEw==" I'm running into this exception:
javax.crypto.BadPaddingException: Given final block not properly padded.
Such issues can arise if a bad key is used during decryption.
Imho this indicates that the key your're using on Java-side is not the same as on C#-side (we don't see the real input
to Encrypt and I don't know what "CustomKey" is doing :-).
Could you please print out
the aeskey and -iv from your C#-Encrypt method directly after you setup them in encryptor-inits and share them here,
that might be usefull for us to help.
public string Encrypt(string data, string key)
...
// Set key and IV
var aesKey = new byte[32];
Array.Copy(_key, 0, aesKey, 0, 32);
encryptor.Key = aesKey;
encryptor.IV = _iv;
==> print aesKey & _iv
...
I referred to the below link
AES Encryption .net to swift,
But, applying the same for ANDROID, I am not able to get the correct AES encryption with version(PBKDF2) conversion for my code. NEED HELP.
public static String Encrypt(String PlainText) throws Exception {
try {
byte[] salt = new byte[] { 0x49, 0x76, 0x61, 0x6E, 0x20, 0x4D,
0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 };
System.out.println("Exception setting up cipher: "+pbkdf2("<keyname>",salt.toString(),1024,128));
Cipher _aesCipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
byte[] keyBytes =pbkdf2("<keyname>",salt.toString(),1024,128).getBytes();
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
byte[] iv ="OFRna73m*aze01xY".getBytes();//pbkdf2("<keyname>",salt.toString(),2,64).getBytes();
IvParameterSpec ivSpec = new IvParameterSpec(iv);
_aesCipher.init(1, keySpec, ivSpec);
byte[] plainText = PlainText.getBytes();
byte[] result = _aesCipher.doFinal(plainText);
return Base64.encodeToString(result, Base64.DEFAULT);//Base64.encode(result,1));
} catch (Exception ex1) {
System.out.println("Exception setting up cipher: "
+ ex1.getMessage() + "\r\n");
ex1.printStackTrace();
return "";
}
}
public static String pbkdf2(String password, String salt, int iterations, int keyLength) throws NoSuchAlgorithmException, InvalidKeySpecException {
char[] chars = password.toCharArray();
PBEKeySpec spec = new PBEKeySpec(chars, salt.getBytes(), iterations, keyLength);
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] hash = skf.generateSecret(spec).getEncoded();
return toHex(hash);
}
// Converts byte array to a hexadecimal string
private static String toHex(byte[] array) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < array.length; i++) {
sb.append(Integer.toString((array[i] & 0xff) + 0x100, 16).substring(1));
}
return sb.toString();
}
Please check below code .
I have created Singletone class for the same so that i can access it anywhere in app.
Below Points Should be same like .net or swift
Important Points are IV , SALT and PASSWORD
Please check this too PBKDF2WithHmacSHA1
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
to generate key we used this
KeySpec spec = new PBEKeySpec(password, salt, 2, 256);
Importnant points are (password, salt,iterantion,bytes) this must be same like other platform which you are using with like .net or swift
public class AesBase64Wrapper {
private static String IV = "it should be same like server or other platform";
private static String PASSWORD = "it should be same like server or other platform";
private static String SALT = "it should be same like server or other platform";
private static volatile AesBase64Wrapper sSoleInstance = new AesBase64Wrapper();
//private constructor.
private AesBase64Wrapper() {
}
public static AesBase64Wrapper getInstance() {
return sSoleInstance;
}
// For Encryption
public String encryptAndEncode(String raw) {
try {
Cipher c = getCipher(Cipher.ENCRYPT_MODE);
byte[] encryptedVal = c.doFinal(getBytes(raw));
//String retVal = Base64.encodeToString(encryptedVal, Base64.DEFAULT);
String retVal = Base64.encodeToString(encryptedVal, Base64.NO_WRAP);
return retVal;
}catch (Throwable t) {
throw new RuntimeException(t);
}
}
public String decodeAndDecrypt(String encrypted) throws Exception {
// byte[] decodedValue = Base64.decode(getBytes(encrypted),Base64.DEFAULT);
byte[] decodedValue = Base64.decode(getBytes(encrypted), Base64.NO_WRAP);
Cipher c = getCipher(Cipher.DECRYPT_MODE);
byte[] decValue = c.doFinal(decodedValue);
return new String(decValue);
}
private String getString(byte[] bytes) throws UnsupportedEncodingException {
return new String(bytes, "UTF-8");
}
private byte[] getBytes(String str) throws UnsupportedEncodingException {
return str.getBytes("UTF-8");
}
private Cipher getCipher(int mode) throws Exception {
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = getBytes(IV);
String xyz = String.valueOf(generateKey());
Log.i("generateKey", xyz);
c.init(mode, generateKey(), new IvParameterSpec(iv));
return c;
}
private Key generateKey() throws Exception {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
char[] password = PASSWORD.toCharArray();
byte[] salt = getBytes(SALT);
KeySpec spec = new PBEKeySpec(password, salt, 2, 256);
SecretKey tmp = factory.generateSecret(spec);
byte[] encoded = tmp.getEncoded();
byte b = encoded[1];
Log.e("Secrete Key", String.valueOf(encoded));
return new SecretKeySpec(encoded, "CBC");
}
}
In Activity you can use it like
String EncryptString = AesBase64Wrapper.getInstance().encryptAndEncode("hello");
String DecryptString = AesBase64Wrapper.getInstance().encryptAndEncode(EncryptString);
// You will Get Output in Decrypted String
Help me on Java equivalent of PHP AES Encryption.
I tried with java AES encryption it was working but the below equivalent php code not giving correct encryption decryption with java
I have given php and equivalent java code, but result is not expected one.
PHP code:
function encrypt($plainText)
{
$key='12345678912345671234567891234567'; //size 32
$md5=md5($key);
$plainText='I am plain text';
$secretKey = hextobin($md5);
$initVector = pack("C*", 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f);
$openMode = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '','cbc', '');
$blockSize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, 'cbc');
$plainPad = pkcs5_pad($plainText, $blockSize);
if (mcrypt_generic_init($openMode, $secretKey, $initVector) != -1)
{
$encryptedText = mcrypt_generic($openMode, $plainPad);
mcrypt_generic_deinit($openMode);
}
$data = bin2hex($encryptedText);
return $data;
}
function decrypt($encryptedText)
{
$key='12345678912345671234567891234567';
$md5=md5($key);
$secretKey = hextobin($md5);
$initVector = pack("C*", 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f);
$encryptedText=hextobin($encryptedText);
$openMode = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '','cbc', '');
mcrypt_generic_init($openMode, $secretKey, $initVector);
$decryptedText = mdecrypt_generic($openMode, $encryptedText);
$decryptedText = rtrim($decryptedText, "\0");
mcrypt_generic_deinit($openMode);
return $decryptedText;
}
//*********** Padding Function *********************
function pkcs5_pad ($plainText, $blockSize)
{
$pad = $blockSize - (strlen($plainText) % $blockSize);
return $plainText . str_repeat(chr($pad), $pad);
}
//********** Hexadecimal to Binary function for php 4.0 version ********
function hextobin($hexString)
{
$length = strlen($hexString);
$binString="";
$count=0;
while($count<$length)
{
$subString =substr($hexString,$count,2);
$packedString = pack("H*",$subString);
if ($count==0)
{
$binString=$packedString;
}
else
{
$binString.=$packedString;
}
$count+=2;
}
return $binString;
}
Java code:
public class StatusAES2 {
private static final String key = "12345678912345671234567891234567";
public static void main(String[] args) {
String plainText = "I am plain text";
System.out.println("Original String to encrypt - " + plainText);
String encryptedString = encrypt(plainText);
System.out.println("Encrypted String - " + encryptedString);
String decryptedString = decrypt(encryptedString);
System.out.println("After decryption - " + decryptedString);
}
public static String encrypt(String value) {
try {
byte[] keybytes=key.getBytes("UTF-8");
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] thedigest = md.digest(keybytes);
String md5Str=Hex.encodeHexString(thedigest);
IvParameterSpec iv = new IvParameterSpec(new byte[]{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15});
keybytes=hextobin(md5Str).getBytes();
SecretKeySpec skeySpec = new SecretKeySpec(keybytes, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(value.getBytes());
String encryptedText=Hex.encodeHexString(encrypted);//bin2hex
return encryptedText;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static String decrypt(String encrypted) {
try {
byte[] keybytes=key.getBytes("UTF-8");
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] thedigest = md.digest(keybytes);
String md5Str=Hex.encodeHexString(thedigest);
IvParameterSpec iv = new IvParameterSpec(new byte[]{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15});
keybytes=hextobin(md5Str).getBytes();
SecretKeySpec skeySpec = new SecretKeySpec(keybytes, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] original = cipher.doFinal(Hex.decodeHex(encrypted.toCharArray()));
return new String(original);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static String hextobin(String s) throws DecoderException, UnsupportedEncodingException {
int length=s.length();
int count=0;
String binString="";
while(count<length){
int c=count+2;
String subs=s.substring(count,c);
String packedString="";
byte[] somevar = DatatypeConverter.parseHexBinary(subs);
byte[] bytes = Hex.decodeHex(subs.toCharArray());
packedString=new String(bytes, "UTF-8");
if (count==0){
binString=packedString;
}else {
binString=binString+packedString;
}
count=count+2;
}
return binString;
}
}
Add this dependency.
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId>
<version>1.46</version>
</dependency>
Try this
CBCBlockCipher cbcBlockCipher = new CBCBlockCipher(new AESEngine());
SecureRandom random = new SecureRandom();
KeyParameter key = new KeyParameter(yourSecretKey);
BlockCipherPadding blockCipherPadding = new PKCS7Padding();
PaddedBufferedBlockCipher pbbc = new PaddedBufferedBlockCipher(cbcBlockCipher, blockCipherPadding);
private byte[] processing(byte[] input, boolean encrypt) throws DataLengthException, InvalidCipherTextException {
int blockSize = cbcBlockCipher.getBlockSize();
int inputOffset = 0;
int inputLength = input.length;
int outputOffset = 0;
byte[] initializationVector = new byte[blockSize];
if (encrypt) {
random.nextBytes(initializationVector);
outputOffset += blockSize;
} else {
System.arraycopy(input, 0, initializationVector, 0, blockSize);
inputOffset += blockSize;
inputLength -= blockSize;
}
pbbc.init(encrypt, new ParametersWithIV(key, initializationVector));
byte[] output = new byte[pbbc.getOutputSize(inputLength) + outputOffset];
if (encrypt) {
System.arraycopy(initializationVector, 0, output, 0, blockSize);
}
int outputLength = outputOffset + pbbc.processBytes(input, inputOffset, inputLength, output, outputOffset);
outputLength += pbbc.doFinal(output, outputLength);
return Arrays.copyOf(output, outputLength);
}
I want to use the PBE to generate other encryption keys.
public SecretKey generateKey(String Ags) throws Exception {
// make password
PBEKeySpec keySpec = new PBEKeySpec(this.password.toCharArray(),this.salt,20,56);
SecretKeyFactory keyFactory = SecretKeyFactory
.getInstance("PBE");
SecretKey key = keyFactory.generateSecret(keySpec);
System.out.println();
/*
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(k);
//
SecretKey FINAL_key = new SecretKeySpec(key.getEncoded(), "AES");
*/
return null;
}
My basic idea is use PBEKeySpec and SecretKeyFactory to generate the PBE key first, and then get the first few bytes, let's say 10 bytes, to generate the AES key. However, after searching the Internet, I still don't know how to get the final key as a byte[]. key.getEncoded() will just give me the input password. How do I get the final key as a byte[]?
As far as i understand by reading the the documentation, i understand that if you want to create a AES secret key you need to feed the algorithm with an at least 128 bit of a key.
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
so to generate key why do you insist getting the 128 bits from the PBE key, instead you can use
byte[] key = (Password+Username).getBytes("UTF-8"); // depends on your implementation
MessageDigest sha = MessageDigest.getInstance("SHA-1");
key = sha.digest(key);
key = Arrays.copyOf(key, 16); // AES uses 16 byte of key as a parameter (?)
you can also use the PBE key to feed SHA and get the bytes in that way. Okey let's turn to your problem, here is a full working code from my security folder, i remember this worked for me, please feel free to ask any questions. In the code below, if you check you'll see that the key is generated using the pbeKeySpec however when i review the code, i cannot see what's your fault though.
public void testPBEWithSHA1AndAES() throws Exception {
String password = "test";
String message = "Hello World!";
byte[] salt = { (byte) 0xc7, (byte) 0x73, (byte) 0x21, (byte) 0x8c,
(byte) 0x7e, (byte) 0xc8, (byte) 0xee, (byte) 0x99 };
byte[] iv = { (byte) 0xc7, (byte) 0x73, (byte) 0x21, (byte) 0x8c,
(byte) 0x7e, (byte) 0xc8, (byte) 0xee, (byte) 0x99,
(byte) 0xc7, (byte) 0x73, (byte) 0x21, (byte) 0x8c,
(byte) 0x7e, (byte) 0xc8, (byte) 0xee, (byte) 0x99 };
int count = 1024;
// int keyLength = 256;
int keyLength = 128;
String cipherAlgorithm = "AES/CBC/PKCS5Padding";
String secretKeyAlgorithm = "PBKDF2WithHmacSHA1";
SecretKeyFactory keyFac = SecretKeyFactory
.getInstance(secretKeyAlgorithm);
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray(), salt,
count, keyLength);
SecretKey tmp = keyFac.generateSecret(pbeKeySpec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher ecipher = Cipher.getInstance(cipherAlgorithm);
ecipher.init(Cipher.ENCRYPT_MODE, secret, new IvParameterSpec(iv));
// decrypt
keyFac = SecretKeyFactory.getInstance(secretKeyAlgorithm);
pbeKeySpec = new PBEKeySpec(password.toCharArray(), salt, count,
keyLength);
tmp = keyFac.generateSecret(pbeKeySpec);
secret = new SecretKeySpec(tmp.getEncoded(), "AES");
// AlgorithmParameters params = ecipher.getParameters();
// byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV();
Cipher dcipher = Cipher.getInstance(cipherAlgorithm);
dcipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
byte[] encrypted = ecipher.doFinal(message.getBytes());
byte[] decrypted = dcipher.doFinal(encrypted);
assertEquals(message, new String(decrypted));
ByteArrayOutputStream out = new ByteArrayOutputStream();
CipherOutputStream cipherOut = new CipherOutputStream(out, ecipher);
cipherOut.write(message.getBytes());
StreamUtils.closeQuietly(cipherOut);
byte[] enc = out.toByteArray();
ByteArrayInputStream in = new ByteArrayInputStream(enc);
CipherInputStream cipherIn = new CipherInputStream(in, dcipher);
ByteArrayOutputStream dec = new ByteArrayOutputStream();
StreamUtils.copy(cipherIn, dec);
assertEquals(message, new String(dec.toByteArray()));
}
I made a password generating program some time ago in java.
it generated passwords based on an input string and password.
it used: pbewithMD5andDES
now i'm making a new version of this for mobile devices in javascript.
i found the library crypto-js witch allows me to generate MD5-hashes and encrypt using DES
but i can't seem to generate identical passwords
what am i doing wrong?
java version:
public static String generate(String password, String passphase) throws Exception {
try {
PBEKeySpec pbeKeySpec = new PBEKeySpec(passphase.toCharArray());
PBEParameterSpec pbeParamSpec;
SecretKeyFactory keyFac;
// Salt
byte[] salt = {(byte) 0xc8, (byte) 0x73, (byte) 0x61, (byte) 0x1d, (byte) 0x1a, (byte) 0xf2, (byte) 0xa8, (byte) 0x99};
// Iteration count
int count = 20;
// Create PBE parameter set
pbeParamSpec = new PBEParameterSpec(salt, count);
keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
// Create PBE Cipher
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
// Initialize PBE Cipher with key and parameters
pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);
// Our cleartext
byte[] cleartext = password.getBytes();
// Encrypt the cleartext
byte[] ciphertext = pbeCipher.doFinal(cleartext);
return byteArrayToHexString(ciphertext).substring(0, 12);
} catch (Exception ex) {
throw new Exception(ex.getMessage());
}
}
public static String byteArrayToHexString(byte[] b){
StringBuilder sb = new StringBuilder(b.length * 2);
for (int i = 0; i < b.length; i++){
int v = b[i] & 0xff;
if (v < 16) {
sb.append('0');
}
sb.append(Integer.toHexString(v));
}
return sb.toString().toUpperCase();
}
the new javascript version (not compete): (i tried both orders: first hashing then DES, and the oher way around)
var hashedPassword = CryptoJS.MD5(password);
var encryptedPassword = CryptoJS.DES.encrypt(hashedPassword, passphrase).toString();
var result = encryptedPassword.toString().substring(0, 12).toUpperCase();
am i on the right way?