var get = function(a) {
var b = CryptoJS.MD5('contentWindowHig');
var c = CryptoJS.enc.Utf8.parse(b);
var d = CryptoJS.enc.Utf8.parse('contentDocuments');
var e = CryptoJS.AES.encrypt(a, c, {
iv: d,
mode: CryptoJS.mode.CBC
pad: CryptoJS.pad.ZeroPadding
});
return e.toString()
}
}
java output is not the same
input plain text: 8d3fj5T7lPMjMfMTyzdbl6Aq95zSUrmuChBFf/ex3lF23jHweq9ABJmEbd7+4z5DmjmhvTVyXWoeoFWCv6xCPFw7CAx7n9RZ9x9fOVrY3Cy+Nm1TAThsjgOjjK+M1S3XIim39NiRp55ai/dm2+E+NzRGPN0wW1bc9Q
js output data:
a: 8d3fj5T7lPMjMfMTyzdbl6Aq95zSUrmuChBFf/ex3lF23jHweq9ABJmEbd7+4z5DmjmhvTVyXWoeoFWCv6xCPFw7CAx7n9RZ9x9fOVrY3Cy+Nm1TAThsjgOjjK+M1S3XIim39NiRp55ai/dm2+E+NzRGPN0wW1bc9Q
b: a165f267f74aba5ded7563ebae2c5ac0
c: 6131363566323637663734616261356465643735363365626165326335616330
d: 636f6e74656e74446f63756d656e7473
e(output): YzYv1oDPuHMyvtt8dgHUOdKaTev3rDtDXu9O%2BBlnCt4X118BroqK7nDjc%2Bo6cb6aoik6KAvIhZwENjkmrMvF26xhhWATh0TrlK0ZWPotNWI9mXWW1FgZtRrFkQGn6%2F4BWY8D%2BAfLxePup4rAw%2BekHjpkFsSZcY6rlL37uUKU%2F6OTdN4rrjG3FOEmN8yDZ9sMNAXu%2FdmAqgFRJ77gvWjgKZEXvhqYqaH1Ukb9eZYMRAE%3D
base64 utf-8 aes iv key confused me...
java output data:
b: a165f267f74aba5ded7563ebae2c5ac0
c: 6131363566323637663734616261356465643735363365626165326335616330
d: 636F6E74656E74446F63756D656E7473
enc_data: fPkNBugoCDHtBLO4tv9VcfGNCWxbqdWryrOWPXrsqN2I0IzNfTN+Smh5PQX5fKsGuHtGWFv7Lryh
jEgOSUJNskH/JD1agfWfzDClSWA7eF4bpKmTg3ch8mrHHI7nwDm4t6jQEeCfDGcQ3Sa8s0UPipOR
wcOTdGVl7RmgJ5gIERQ45m34fm8tveMYrXyTgvDKbvqO7toqshcg6IOxNgB5OCr/DH4xQibnYPnk
0Z4EBy8=
encoded_str: fPkNBugoCDHtBLO4tv9VcfGNCWxbqdWryrOWPXrsqN2I0IzNfTN%2BSmh5PQX5fKsGuHtGWFv7Lryh%0D%0AjEgOSUJNskH%2FJD1agfWfzDClSWA7eF4bpKmTg3ch8mrHHI7nwDm4t6jQEeCfDGcQ3Sa8s0UPipOR%0D%0AwcOTdGVl7RmgJ5gIERQ45m34fm8tveMYrXyTgvDKbvqO7toqshcg6IOxNgB5OCr%2FDH4xQibnYPnk%0D%0A0Z4EBy8%3D
import com.pplive.common.util.LogUtil;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import sun.misc.BASE64Encoder;
public static void main(String[] args) {
// key: 8d3fj5T7lPMjMfMTyzdbl6Aq95zSUrmuChBFf/ex3lF23jHweq9ABJmEbd7+4z5DmjmhvTVyXWoeoFWCv6xCPFw7CAx7n9RZ9x9fOVrY3Cy+Nm1TAThsjgOjjK+M1S3XIim39NiRp55ai/dm2+E+NzRGPN0wW1bc9Q
// b: a165f267f74aba5ded7563ebae2c5ac0
// c: 6131363566323637663734616261356465643735363365626165326335616330
// d: 636f6e74656e74446f63756d656e7473
//ss: YzYv1oDPuHMyvtt8dgHUOdKaTev3rDtDXu9O%2BBlnCt4X118BroqK7nDjc%2Bo6cb6aoik6KAvIhZwENjkmrMvF26xhhWATh0TrlK0ZWPotNWI9mXWW1FgZtRrFkQGn6%2F4BWY8D%2BAfLxePup4rAw%2BekHjpkFsSZcY6rlL37uUKU%2F6OTdN4rrjG3FOEmN8yDZ9sMNAXu%2FdmAqgFRJ77gvWjgKZEXvhqYqaH1Ukb9eZYMRAE%3D
//int end = html.indexOf("\")", start);
//String plaintext = html.substring(start + "encodeURIComponent(get(\"".length(), end);
String plaintext = "8d3fj5T7lPMjMfMTyzdbl6Aq95zSUrmuChBFf/ex3lF23jHweq9ABJmEbd7+4z5DmjmhvTVyXWoeoFWCv6xCPFw7CAx7n9RZ9x9fOVrY3Cy+Nm1TAThsjgOjjK+M1S3XIim39NiRp55ai/dm2+E+NzRGPN0wW1bc9Q";
System.out.println("plaintext: " + plaintext);
try {
String b = EncoderByMd5("contentWindowHig");
System.out.println("b: " + b);
String c = byteToHexString(b.getBytes("utf-8"));
System.out.println("c: " + c);
String d = byteToHexString("contentDocuments".getBytes("utf-8"));
System.out.println("d: " + d);
String enc_data = AES_CBC_Encrypt_nopadding(
plaintext.getBytes("utf-8"),
b.getBytes(),
"contentDocuments".getBytes());
System.out.println("enc_data: " + enc_data);
String encoded_str = URLEncoder.encode(enc_data, "utf-8");
System.out.println("encoded_str: " + encoded_str);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
public static String AES_CBC_Encrypt_nopadding(byte[] content, byte[] keyBytes, byte[] iv){
try{
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128, new SecureRandom(keyBytes));
SecretKey key = keyGenerator.generateKey();
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
int blockSize = cipher.getBlockSize();
// process plain text
int plaintextLength = content.length;
if (plaintextLength % blockSize != 0) {
plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
}
byte[] plaintext = new byte[plaintextLength];
System.arraycopy(content, 0, plaintext, 0, content.length);
for (int i=content.length;i<plaintextLength;i++) {
plaintext[i] = (byte)0;
}
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
byte[] encrypted = cipher.doFinal(plaintext);
BASE64Encoder base64en = new BASE64Encoder();
return base64en.encode(encrypted);
}catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("exception:"+e.toString());
}
return null;
}
public static String EncoderByMd5(String str) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest md5=MessageDigest.getInstance("MD5");
md5.update(str.getBytes());
return new BigInteger(1, md5.digest()).toString(16);
}
public static String AES_CBC_Decrypt(byte[] content, byte[] keyBytes, byte[] iv){
try{
KeyGenerator keyGenerator=KeyGenerator.getInstance("AES");
keyGenerator.init(128, new SecureRandom(keyBytes));//key长可设为128,192,256位,这里只能设为128
SecretKey key=keyGenerator.generateKey();
Cipher cipher=Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
byte[] result = cipher.doFinal(content);
BASE64Encoder base64en = new BASE64Encoder();
return base64en.encode(result);
}catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("exception:"+e.toString());
}
return null;
}
//Converting a string of hex character to bytes
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 String byteToHexString(byte[] bytes) {
StringBuffer sb = new StringBuffer(bytes.length);
String sTemp;
for (int i = 0; i < bytes.length; i++) {
sTemp = Integer.toHexString(0xFF & bytes[i]);
if (sTemp.length() < 2)
sb.append(0);
sb.append(sTemp.toUpperCase());
}
return sb.toString();
}
so easy .
js convert to java
// var b = CryptoJS.MD5('contentWindowHig');
String b = org.apache.commons.codec.digest.DigestUtils.md5Hex("contentWindowHig");
// var c = CryptoJS.enc.Utf8.parse(b);
byte[] c = b.getByte("UTF-8");
// var d = CryptoJS.enc.Utf8.parse('contentDocuments');
byte[] d = "contentDocuments".getByte("UTF-8");
/* var e = CryptoJS.AES.encrypt(a, c, {
iv: d,
mode: CryptoJS.mode.CBC
pad: CryptoJS.pad.ZeroPadding
});
return e.toString()
*/
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(c, "AES"), new IvParameterSpec(d));
Base64.getEncoder().encodeToString(cipher.doFinal(a.getBytes("utf-8")));
a is encrypt str
Related
In Java code, i have source work well, this is use for encrypt:
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Base64;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class HelloWorld{
private static final String hexKey = "B8EE12E123C0E300A202074A153CC0D27D739357480FFFFFFFFFFFFFFFFFFFEF";
public static void main(String []args){
System.out.println("Encryt ==== ");
String textToEncrypt = "From=ABC&Key=FootID1234&Value=ResultValue2324";
String encryptedText = encrypt(textToEncrypt);
System.out.println(encryptedText);
System.out.println("Decrypt ==== ");
String decryptedText = decrypt(encryptedText);
System.out.println(decryptedText);
}
public static String encrypt (String plainText) {
String encryptedText = null;
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
SecretKeySpec secretKey = new SecretKeySpec(hexToBytes(hexKey), "AES");
IvParameterSpec ivparameterspec = new IvParameterSpec(hexKey.getBytes(), 0, 16);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivparameterspec);
byte[] cipherText = cipher.doFinal(plainText.getBytes("UTF8"));
encryptedText = bytesToHex(cipherText);
} catch (Exception E) {
System.out.println("Encrypt Exception : " + E.getMessage());
}
return encryptedText;
}
public static String decrypt(String encryptedText) {
String decryptedText = null;
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
SecretKeySpec secretKey = new SecretKeySpec(hexToBytes(hexKey), "AES");
IvParameterSpec ivparameterspec = new IvParameterSpec(hexKey.getBytes("UTF8"), 0, 16);
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivparameterspec);
byte[] cipherText = hexToBytes(encryptedText);
byte[] dcrbyte = cipher.doFinal(cipherText);
decryptedText = new String(dcrbyte, "UTF-8");
} catch (Exception E) {
System.out.println("Encrypt Exception : " + E.getMessage());
}
return decryptedText;
}
private static byte[] hexToBytes(String hexStr) {
byte[] val = new byte[hexStr.length() / 2];
for (int i = 0; i < val.length; i++) {
int idx = i * 2;
int j = Integer.parseInt(hexStr.substring(idx, idx + 2), 16);
val[i] = (byte) j;
}
return val;
}
private static String bytesToHex(byte[] hashInBytes) {
char[] hexArray = "0123456789ABCDEF".toCharArray();
char[] hexChars = new char[hashInBytes.length * 2];
for (int i = 0; i < hashInBytes.length; i++) {
int v = hashInBytes[i] & 0xFF;
hexChars[i * 2] = hexArray[v >>> 4];
hexChars[i * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
}
And in c#, i try to write decryptAes() function like this:
public static class Encryption
{
// use these parameters to test decryptAes()
//string key = "B8EE12E123C0E300A202074A153CC0D27D739357480FFFFFFFFFFFFFFFFFFFEF";
//string textToDecrypt = "756AD4D80E2CF1E289D55A23E092F012E8D5F372A343A419BC87F77B6335F04EFB41C3B56F5CDA167F90F67CD672A186";
public static string decryptAes(string key, string textToDecrypt)
{
RijndaelManaged rijndaelCipher = new RijndaelManaged();
// Assumed Mode and padding values.
rijndaelCipher.Mode = CipherMode.CBC;
rijndaelCipher.Padding = PaddingMode.PKCS7;
// AssumedKeySize and BlockSize values.
rijndaelCipher.KeySize = 0x80; //128
rijndaelCipher.BlockSize = 0x80;
// Convert Hex keys to byte Array.
byte[] encryptedData = HexToBytes(textToDecrypt);
//byte[] pwdBytes = System.Text.Encoding.GetEncoding("UTF-8").GetBytes(key);
byte[] pwdBytes = HexToBytes(key);
byte[] keyBytes = new byte[0x10]; //16
int len = pwdBytes.Length;
if (len > keyBytes.Length)
{
len = keyBytes.Length;
}
Array.Copy(pwdBytes, keyBytes, len);
rijndaelCipher.Key = keyBytes;
rijndaelCipher.IV = keyBytes;
// Decrypt data
byte[] plainText = rijndaelCipher.CreateDecryptor()
.TransformFinalBlock(encryptedData, 0, encryptedData.Length);
return Encoding.UTF8.GetString(plainText);
}
public static byte[] HexToBytes(string str)
{
if (str.Length == 0 || str.Length % 2 != 0)
return new byte[0];
byte[] buffer = new byte[str.Length / 2];
char c;
for (int bx = 0, sx = 0; bx < buffer.Length; ++bx, ++sx)
{
// Convert first half of byte
c = str[sx];
buffer[bx] = (byte)((c > '9' ? (c > 'Z' ? (c - 'a' + 10) : (c - 'A' + 10)) : (c - '0')) << 4);
// Convert second half of byte
c = str[++sx];
buffer[bx] |= (byte)(c > '9' ? (c > 'Z' ? (c - 'a' + 10) : (c - 'A' + 10)) : (c - '0'));
}
return buffer;
}
public static string ByteToHex(byte[] ba)
{
StringBuilder hex = new StringBuilder(ba.Length * 2);
foreach (byte b in ba)
hex.AppendFormat("{0:x2}", b);
return hex.ToString().ToUpper();
}
}
But the c# decryptAes() function does not work as i expect. An error
System.Security.Cryptography.CryptographicException: 'Padding is invalid and cannot be removed.'
has occured at line rijndaelCipher.Padding = PaddingMode.PKCS7;
When i change to rijndaelCipher.Padding = PaddingMode.None, it does not work as i expect, the c# result is not the same as the result of java.
Please help, any advice would be appreciated!
Thanks!
You need to explicitly set the padding for both encryption and decryption. Unless you have a reason to do otherwise, use PKCS#7 padding.
rijndaelCipher.Padding=PaddingMode.none;
Java code :
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class AESSecurityUtil {
private static final String AES = "AES";
private static final String CHARSET_NAME = "utf-8";
private static SecretKeySpec getKey(String password) throws NoSuchAlgorithmException{
KeyGenerator kgen = KeyGenerator.getInstance(AES);
SecureRandom random=SecureRandom.getInstance("SHA1PRNG");
random.setSeed(password.getBytes());
kgen.init(128, random);
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec(enCodeFormat, AES);
return key;
}
public static String encode(String str, String password)
{
byte[] arr = encodeToArr(str, password);
return byteArrToString(arr);
}
private static byte[] encodeToArr(String str, String password)
{
try
{
Cipher cipher = Cipher.getInstance(AES);
byte[] byteContent = str.getBytes(CHARSET_NAME);
cipher.init(Cipher.ENCRYPT_MODE, getKey(password));
byte[] result = cipher.doFinal(byteContent);
return result;
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
public static String decode(String hexStr, String password){
byte[] arr = string2ByteArr(hexStr);
return decode(arr, password);
}
private static String decode(byte[] arr, String password) {
try{
Cipher cipher = Cipher.getInstance(AES);
cipher.init(Cipher.DECRYPT_MODE, getKey(password));
byte[] result = cipher.doFinal(arr);
return new String(result, CHARSET_NAME);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
private static String byteArrToString(byte[] arr) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i <arr.length; i++) {
String s = Integer.toString(arr[i] + 128, 16);
if (s.length() == 1){
s = "0" + s;
}
sb.append(s);
}
return sb.toString().toUpperCase();
}
private static byte[] string2ByteArr(String s) {
s = s.toUpperCase();
String str = "0123456789ABCDEF";
byte[] arr = new byte[s.length() / 2];
for (int i = 0; i <arr.length; i++){
char s1 = s.charAt(i * 2);
char s2 = s.charAt(i * 2 + 1);
int tmp1 = str.indexOf(s1) * 16;
int tmp2 = str.indexOf(s2);
arr[i] = (byte) (tmp1 + tmp2 - 128);
}
return arr;
}
public static void main(String[] args) throws Exception {
System.out.println(decode("03AB8A3B85AFDD3926850B14C1BFF608", "imcc"));
String keyStr = "UITN25LMUQC436IM";
String plainText = "this is a string will be AES_Encrypt";
String encText = encode(plainText,keyStr);
String decString = decode(encText,keyStr);
System.out.println(encText);
System.out.println(decString);
}
}
Does the class can turn into a php code to achieve encryption and decryption ? I think the problem is that the getKey method can not achieve in php.
This Java class, provided by the platform side, can not require making changes.
Please tell me where the problem is?
Thanks
Append ...my PHP code:
<?php
if (!function_exists('hex2bin')) {
function hex2bin($str) {
$sbin = "";
$len = strlen($str);
for ($i = 0; $i < $len; $i += 2) {
$sbin .= pack("H*", substr($str, $i, 2));
}
return $sbin;
}
}
class Util_AesEncrypt {
private $_cipher = MCRYPT_RIJNDAEL_128;
private $_mode = MCRYPT_MODE_ECB;
private function _pkcs5Pad($text, $blockSize) {
$pad = $blockSize - (strlen($text) % $blockSize);
return $text . str_repeat(chr($pad), $pad);
}
private function _pkcs5Unpad($text) {
$end = substr($text, -1);
$last = ord($end);
$len = strlen($text) - $last;
if (substr($text, $len) == str_repeat($end, $last)) {
return substr($text, 0, $len);
}
return false;
}
public function encrypt($encrypt, $key) {
$blockSize = mcrypt_get_block_size($this->_cipher, $this->_mode);
$paddedData = $this->_pkcs5Pad($encrypt, $blockSize);
$ivSize = mcrypt_get_iv_size($this->_cipher, $this->_mode);
$iv = mcrypt_create_iv($ivSize, MCRYPT_RAND);
$encrypted = mcrypt_encrypt($this->_cipher, $key, $paddedData, $this->_mode, $iv);
return bin2hex($encrypted);
}
public function decrypt($decrypt, $key) {
$decoded = hex2bin($decrypt);
$blockSize = mcrypt_get_iv_size($this->_cipher, $this->_mode);
$iv = mcrypt_create_iv($blockSize, MCRYPT_RAND);
$decrypted = mcrypt_decrypt($this->_cipher, $key, $decoded, $this->_mode, $iv);
return $this->_pkcs5Unpad($decrypted);
}
}
$keyStr = 'UITN25LMUQC436IM';
$plainText = 'this is a string will be AES_Encrypt';
$aes = new Util_AesEncrypt();
$encText = $aes->encrypt($plainText, $keyStr);
$decString = $aes->decrypt($encText, $keyStr);
echo $encText, "\n", $decString;
Different encryption results
The JAVA getKey() function will get 128bit key from password use SHA1PRNG, you can use this PHP code to get key from password:
$key = substr(openssl_digest(openssl_digest($password, 'sha1', true), 'sha1', true), 0, 16);
I also spent a lot of time in this case, Good Luck.
I have a requirement to AES Encrypt (with initial vector) an NSString value.But it gives different output on comparing with the java code provided below.In Java it is delivering the correct result.What could be the reason?
For that I have used the code below:
iOS
- (NSData *)AES256EncryptWithKey:(NSString *)key
{
// 'key' should be 32 bytes for AES256, will be null-padded otherwise
char keyPtr[kCCKeySizeAES128+1]; // room for terminator (unused)
bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)
// fetch key data
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
//See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES128 ,
INTIAL_VECTOR /* initialization vector (optional) */,
[self bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer); //free the buffer;
return nil;
}
- (NSString*)hexStringFromData:(NSData *)data
{
unichar* hexChars = (unichar*)malloc(sizeof(unichar) * (data.length*2));
unsigned char* bytes = (unsigned char*)data.bytes;
for (NSUInteger i = 0; i < data.length; i++) {
unichar c = bytes[i] / 16;
if (c < 10) c += '0';
else c += 'a' - 10;
hexChars[i*2] = c;
c = bytes[i] % 16;
if (c < 10) c += '0';
else c += 'a' - 10;
hexChars[i*2+1] = c;
}
NSString* retVal = [[NSString alloc] initWithCharactersNoCopy:hexChars
length:data.length*2
freeWhenDone:YES];
return [retVal autorelease];
}
The implementation snippet is :
NSData *InputData = [#"mahi" dataUsingEncoding:NSUTF8StringEncoding];
NSData *encryptedData = [InputData AES256EncryptWithKey:ENCRYPTION_KEY];
NSString *encryptedHexString = [self hexStringFromData:encryptedData];
NSLog(#"Encrypted HexString : %#",encryptedHexString);
Java
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class MCrypt {
private String iv = "fedcba9876543210";
private IvParameterSpec ivspec;
private SecretKeySpec keyspec;
private Cipher cipher;
private String SecretKey = "0123456789abcdef";
public MCrypt()
{
ivspec = new IvParameterSpec(iv.getBytes());
keyspec = new SecretKeySpec(SecretKey.getBytes(), "AES");
try {
cipher = Cipher.getInstance("AES/CBC/NoPadding");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public byte[] encrypt(String text) throws Exception
{
if(text == null || text.length() == 0)
throw new Exception("Empty string");
byte[] encrypted = null;
try {
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
encrypted = cipher.doFinal(padString(text).getBytes());
} catch (Exception e)
{
throw new Exception("[encrypt] " + e.getMessage());
}
return encrypted;
}
public byte[] decrypt(String code) throws Exception
{
if(code == null || code.length() == 0)
throw new Exception("Empty string");
byte[] decrypted = null;
try {
cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
decrypted = cipher.doFinal(hexToBytes(code));
} catch (Exception e)
{
throw new Exception("[decrypt] " + e.getMessage());
}
return decrypted;
}
public static String bytesToHex(byte[] data)
{
if (data==null)
{
return null;
}
int len = data.length;
String str = "";
for (int i=0; i<len; i++) {
if ((data[i]&0xFF)<16)
str = str + "0" + java.lang.Integer.toHexString(data[i]&0xFF);
else
str = str + java.lang.Integer.toHexString(data[i]&0xFF);
}
return str;
}
public static byte[] hexToBytes(String str) {
if (str==null) {
return null;
} else if (str.length() < 2) {
return null;
} else {
int len = str.length() / 2;
byte[] buffer = new byte[len];
for (int i=0; i<len; i++) {
buffer[i] = (byte) Integer.parseInt(str.substring(i*2,i*2+2),16);
}
return buffer;
}
}
private static String padString(String source)
{
char paddingChar = ' ';
int size = 16;
int x = source.length() % size;
int padLength = size - x;
for (int i = 0; i < padLength; i++)
{
source += paddingChar;
}
return source;
}
}
How do I fix this it keeps throwing exceptions. As you can see i am trying to use an image as a password would you please help program of fix my encrypt/decrypt method so this works. I need help my current code is as follows:
import java.awt.image.*;
import java.io.*;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.*;
import javax.swing.*;
/**
*
* #author Lance Gerday
*/
public class Encrypt {
private static final String ALGORITHM = "AES";
public static byte[] keyValue;
// 500 KB max
public static byte[] valuesRead = new byte[512000];
public static void encrypt(File f) throws Exception {
FileInputStream in = null;
FileOutputStream out = null;
in = new FileInputStream(f);
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGORITHM);
c.init(Cipher.ENCRYPT_MODE, key);//my code seems to fail here
String name = f.getName();
String newFileName = name.substring(0, name.lastIndexOf("."))
+ ".enc" + name.substring(name.lastIndexOf("."), name.length());
File newFile = new File(f.getParentFile(), newFileName);
out = new FileOutputStream(newFile);
//reads the file into valueToEnc and returns the number of bytes read
valuesRead = new byte[Integer.MAX_VALUE];
int numberRead = in.read(valuesRead);
keyValue = new byte[numberRead];
for (int i = 0; i < numberRead; i++) {
keyValue[i] = valuesRead[i];
}
byte[] encValue = c.doFinal(keyValue);
String encryptedValue = new BASE64Encoder().encode(encValue);
out.write(encryptedValue.getBytes());
}
public static void decrypt(File f) throws Exception {
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGORITHM);
c.init(Cipher.DECRYPT_MODE, key);
FileInputStream in = null;
FileOutputStream out = null;
if (f.canRead()) {
in = new FileInputStream(f);
}
String name = f.getName();
String newFileName = name.substring(0, name.lastIndexOf(".enc"));
File newFile = new File(f.getParentFile(), newFileName);
out = new FileOutputStream(newFile);
//reads the file into valueToEnc and returns the number of bytes read
valuesRead = new byte[Integer.MAX_VALUE];
int numberRead = in.read(valuesRead);
keyValue = new byte[numberRead];
for (int i = 0; i < numberRead; i++) {
keyValue[i] = valuesRead[i];
}
String encryptedValue = new String(keyValue);
byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedValue);
byte[] decValue = c.doFinal(decordedValue);
out.write(decValue);
}
private static Key generateKey() throws Exception {
Key key = new SecretKeySpec(keyValue, ALGORITHM);
return key;
}
public static void setKeyValue(File f) {
BufferedImage img = null;
try {
img = javax.imageio.ImageIO.read(f);
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Fail error at line 92");
}
Raster r = img.getData();
int[] data = r.getPixels(r.getMinX(), r.getMinY(), r.getWidth(), r.getHeight(), (int[]) null);
for (int a : data) {
}
int dataLength = data.length;
keyValue = new byte[dataLength << 2];
for (int i = 0; i < dataLength; i++) {
int x = data[i];
int k = i << 2;
keyValue[k++] = (byte) ((x >>> 0) & 0xff);
keyValue[k++] = (byte) ((x >>> 8) & 0xff);
keyValue[k++] = (byte) ((x >>> 16) & 0xff);
keyValue[k++] = (byte) ((x >>> 24) & 0xff);
}
}
}
Though you don't really ask for a question, your secret key isn't really standard. Usually the way to generate is:
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128); // or 192 or 256
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Reference AES and JCE
I'm trying to encrypt data between my android application and a PHP webservice.
I found the next piece of code in this website: http://schneimi.wordpress.com/2008/11/25/aes-128bit-encryption-between-java-and-php/
But when I try to decrypt I get the Exception of the title "data not block size aligned"
This are the method in my MCrypt class
public String encrypt(String text) throws Exception
{
if(text == null || text.length() == 0)
throw new Exception("Empty string");
Cipher cipher;
byte[] encrypted = null;
try {
cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
encrypted = cipher.doFinal(padString(text).getBytes());
} catch (Exception e)
{
throw new Exception("[encrypt] " + e.getMessage());
}
return new String( encrypted );
}
public String decrypt(String code) throws Exception
{
if(code == null || code.length() == 0)
throw new Exception("Empty string");
Cipher cipher;
byte[] decrypted = null;
try {
cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
decrypted = cipher.doFinal(hexToBytes(code));
} catch (Exception e)
{
throw new Exception("[decrypt] " + e.getMessage());
}
return new String( decrypted );
}
private static byte[] hexToBytes(String hex) {
String HEXINDEX = "0123456789abcdef";
int l = hex.length() / 2;
byte data[] = new byte[l];
int j = 0;
for (int i = 0; i < l; i++) {
char c = hex.charAt(j++);
int n, b;
n = HEXINDEX.indexOf(c);
b = (n & 0xf) << 4;
c = hex.charAt(j++);
n = HEXINDEX.indexOf(c);
b += (n & 0xf);
data[i] = (byte) b;
}
return data;
}
private static String padString(String source)
{
char paddingChar = ' ';
int size = 16;
int x = source.length() % size;
int padLength = size - x;
for (int i = 0; i < padLength; i++)
{
source += paddingChar;
}
return source;
}
And this is how I'm using it in my activity to test:
String encrypted = mcrypt.encrypt(jsonUser.toString());
String decrypted = mcrypt.decrypt(encrypted);
the encrypt method works fine, but the second throws an exception.
At last! I made it work! Thanks for all your suggestion. I would like to share the code just in case somebody get stuck like me:
JAVA
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class MCrypt {
private String iv = "fedcba9876543210";//Dummy iv (CHANGE IT!)
private IvParameterSpec ivspec;
private SecretKeySpec keyspec;
private Cipher cipher;
private String SecretKey = "0123456789abcdef";//Dummy secretKey (CHANGE IT!)
public MCrypt()
{
ivspec = new IvParameterSpec(iv.getBytes());
keyspec = new SecretKeySpec(SecretKey.getBytes(), "AES");
try {
cipher = Cipher.getInstance("AES/CBC/NoPadding");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public byte[] encrypt(String text) throws Exception
{
if(text == null || text.length() == 0)
throw new Exception("Empty string");
byte[] encrypted = null;
try {
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
encrypted = cipher.doFinal(padString(text).getBytes());
} catch (Exception e)
{
throw new Exception("[encrypt] " + e.getMessage());
}
return encrypted;
}
public byte[] decrypt(String code) throws Exception
{
if(code == null || code.length() == 0)
throw new Exception("Empty string");
byte[] decrypted = null;
try {
cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
decrypted = cipher.doFinal(hexToBytes(code));
} catch (Exception e)
{
throw new Exception("[decrypt] " + e.getMessage());
}
return decrypted;
}
public static String bytesToHex(byte[] data)
{
if (data==null)
{
return null;
}
int len = data.length;
String str = "";
for (int i=0; i<len; i++) {
if ((data[i]&0xFF)<16)
str = str + "0" + java.lang.Integer.toHexString(data[i]&0xFF);
else
str = str + java.lang.Integer.toHexString(data[i]&0xFF);
}
return str;
}
public static byte[] hexToBytes(String str) {
if (str==null) {
return null;
} else if (str.length() < 2) {
return null;
} else {
int len = str.length() / 2;
byte[] buffer = new byte[len];
for (int i=0; i<len; i++) {
buffer[i] = (byte) Integer.parseInt(str.substring(i*2,i*2+2),16);
}
return buffer;
}
}
private static String padString(String source)
{
char paddingChar = ' ';
int size = 16;
int x = source.length() % size;
int padLength = size - x;
for (int i = 0; i < padLength; i++)
{
source += paddingChar;
}
return source;
}
}
HOW TO USE IT (JAVA)
mcrypt = new MCrypt();
/* Encrypt */
String encrypted = MCrypt.bytesToHex( mcrypt.encrypt("Text to Encrypt") );
/* Decrypt */
String decrypted = new String( mcrypt.decrypt( encrypted ) );
====================================================
PHP
<?php
class MCrypt
{
private $iv = 'fedcba9876543210'; #Same as in JAVA
private $key = '0123456789abcdef'; #Same as in JAVA
function __construct()
{
}
function encrypt($str) {
//$key = $this->hex2bin($key);
$iv = $this->iv;
$td = mcrypt_module_open('rijndael-128', '', 'cbc', $iv);
mcrypt_generic_init($td, $this->key, $iv);
$encrypted = mcrypt_generic($td, $str);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return bin2hex($encrypted);
}
function decrypt($code) {
//$key = $this->hex2bin($key);
$code = $this->hex2bin($code);
$iv = $this->iv;
$td = mcrypt_module_open('rijndael-128', '', 'cbc', $iv);
mcrypt_generic_init($td, $this->key, $iv);
$decrypted = mdecrypt_generic($td, $code);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return utf8_encode(trim($decrypted));
}
protected function hex2bin($hexdata) {
$bindata = '';
for ($i = 0; $i < strlen($hexdata); $i += 2) {
$bindata .= chr(hexdec(substr($hexdata, $i, 2)));
}
return $bindata;
}
}
HOW TO USE IT (PHP)
<?php
$mcrypt = new MCrypt();
#Encrypt
$encrypted = $mcrypt->encrypt("Text to encrypt");
#Decrypt
$decrypted = $mcrypt->decrypt($encrypted);
I'm guessing your keyspec and ivspec are not valid for decryption. I've typically transformed them into PublicKey and PrivateKey instances and then use the private key to decrypt.
I looked at the comments in the other answer. I ran into a similar problem trying to encrypt a large block of text using open SSL in php (on both sides). I imagine the same issue would come up in Java.
If you have a 1024 bit RSA key, you must split the incoming text into 117 byte chunks (a char is a byte) and encrypt each (you can concatenate them together). On the other end, you must split the encrypted data into 128 byte chunks and decrypt each. This should give you your original message.
Also note that http may not play friendly with the non-ASCII encrypted data. I base64 encode/decode it before and after transmission (plus you have to worry about additional urlencoding for the base64 change, but it is easy).
I'm not sure of your AES key length, but if it's 1024 bits the chunk length is probably the same. If it's not, you will have to divide the bits by 8 to find the byte chunk length coming out. I'm actually not sure how to get it coming in, unfortunately (maybe multiply by 117/128 ?)
Here's some php code:
class Crypto {
public function encrypt($key, $data) {
$crypto = '';
foreach (str_split($data, 117) as $chunk) {
openssl_public_encrypt($chunk, $encrypted, $key);
$crypto .= $encrypted;
}
return $crypto;
}
//Decrypt omitted. Basically the same, change 117 to 128.
/**##+
* Update data for HTTP transmission and retrieval
* Must be used on encrypted data, but also useful for any binary data
* (e.g. zip files).
*/
public function base64_encode($value) {
return rtrim(strtr(base64_encode($value), '+/', '-_'), '=');
}
//String length must be padded for decoding for some reason
public function base64_decode($value) {
return base64_decode(str_pad(strtr($value, '-_', '+/')
, strlen($value) % 4, '=', STR_PAD_RIGHT));
}
/**##-*/
}