java cbc加密php,AES CBC 相互加解密 Java/PHP/C++

项目中需要用到加密通讯,因为服务器是用php写的,采用了AES CBC 128位加密,由于是内部系统,所以向量iv就默认内置了。当然也可以采用与aeskey一起存储,加解密的时候分离。

下面是代码:

PHP:

$iv = "1234567890123456"; /* 必须16位哦 */

/* 采用128位加密,密钥也必须是16位 */

function aes_encode($sourcestr, $key)

{

global $iv;

return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $sourcestr, MCRYPT_MODE_CBC, $iv));

}

function aes_decode($crypttext, $key)

{

global $iv;

return rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, base64_decode($crypttext), MCRYPT_MODE_CBC, $iv), "\0");

}

Java:

import javax.crypto.Cipher;

import javax.crypto.spec.IvParameterSpec;

import javax.crypto.spec.SecretKeySpec;

import com.android.util.BASE64.BASE64Decoder;

import com.android.util.BASE64.BASE64Encoder;

/**

*

* @author Tom

*/

public class NewAes {

public static String iv = "1234567890123456";

public static String Encrypt(String sSrc, String sKey) throws Exception {

if (sKey == null) {

System.out.print("Key为空null");

return null;

}

// 判断Key是否为16位

if (sKey.length() != 16) {

System.out.print("Key长度不是16位");

return null;

}

byte[] raw = sKey.getBytes();

SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");

Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");//"算法/模式/补码方式"

IvParameterSpec iv = new IvParameterSpec(NewAes.iv.getBytes());//使用CBC模式,需要一个向量iv,可增加加密算法的强度

cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);

byte[] srawt = sSrc.getBytes();

int len = srawt.length;

/* 计算补0后的长度 */

while(len % 16 != 0) len ++;

byte[] sraw = new byte[len];

/* 在最后补0 */

for (int i = 0; i < len; ++i) {

if (i < srawt.length) {

sraw[i] = srawt[i];

} else {

sraw[i] = 0;

}

}

byte[] encrypted = cipher.doFinal(sraw);

return new BASE64Encoder().encode(encrypted);//此处使用BASE64做转码功能,同时能起到2次加密的作用。

}

// 解密

public static String Decrypt(String sSrc, String sKey) throws Exception {

try {

// 判断Key是否正确

if (sKey == null) {

System.out.print("Key为空null");

return null;

}

// 判断Key是否为16位

if (sKey.length() != 16) {

System.out.print("Key长度不是16位");

return null;

}

System.out.println("key is:"+sKey);

byte[] raw = sKey.getBytes("ASCII");

SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");

Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");

IvParameterSpec iv = new IvParameterSpec(NewAes.iv.getBytes());

cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);

byte[] encrypted1 = new BASE64Decoder().decodeBuffer(sSrc);//先用base64解密

try {

byte[] original = cipher.doFinal(encrypted1);

String originalString = new String(original);

return originalString.trim();

} catch (Exception e) {

System.out.println(e.toString());

return null;

}

} catch (Exception ex) {

System.out.println(ex.toString());

return null;

}

}

}

C++:

char *CryptObject::aes_encode(const char *sourcestr, char *key = "")

{

if (strcmp(key, "") == 0) key = aeskey;

int len = strlen(sourcestr);

unsigned char iv[AES_BLOCK_SIZE+1] = "6543210987654321"; // 注意,iv绝对不能是const的,否则会段错误

unsigned char * out = (unsigned char *)malloc(1024*1024);

if (out == NULL) {

fprintf(stderr, "No Memory!\n");

}

AES_KEY aes;

if(AES_set_encrypt_key((unsigned char*)key, 128, &aes) < 0)

{

return NULL;

}

/* 计算补0后的长度 */

int out_len = ((len - 1) / 16 + 1)* 16;

char * sstr = (char *)malloc(sizeof(char) * out_len + 1);

/* 补0 */

memset(sstr, 0, out_len+1);

strcpy(sstr, sourcestr);

AES_cbc_encrypt((unsigned char*)sstr, out, out_len, &aes, (unsigned char*)iv, AES_ENCRYPT);

/* 这里的长度一定要注意,不能用strlen来获取,加密后的字符串中可能会包含\0 */

char * out2 = base64_encode((char *)out, out_len);

free(out);

free(sstr);

return out2;

}

char *CryptObject::aes_decode(const char *crypttext, char *key = "")

{

if (strcmp(key, "") == 0) key = aeskey;

int out_len = 0;

unsigned char iv[AES_BLOCK_SIZE+1] = "6543210987654321";

char *in = base64_decode(crypttext, strlen(crypttext), out_len);

char *out = (char *) malloc(sizeof(char) * out_len + 1);

memset(out, 0, out_len + 1);

AES_KEY aes;

if(AES_set_decrypt_key((unsigned char*)key, 128, &aes) < 0)

{

return NULL;

}

AES_cbc_encrypt((unsigned char*)in, (unsigned char*)out, out_len, &aes, (unsigned char*)iv, AES_DECRYPT);

free(in);

return out;

}

char *CryptObject::base64_encode(const char *data, int data_len)

{

int prepare = 0;

int ret_len;

int temp = 0;

char *ret = NULL;

char *f = NULL;

int tmp = 0;

char changed[4];

int i = 0;

ret_len = data_len / 3;

temp = data_len % 3;

if (temp > 0)

{

ret_len += 1;

}

ret_len = ret_len*4 + 1;

ret = (char *)malloc(ret_len);

if ( ret == NULL)

{

printf("No enough memory.\n");

exit(0);

}

memset(ret, 0, ret_len);

f = ret;

while (tmp < data_len)

{

temp = 0;

prepare = 0;

memset(changed, '\0', 4);

while (temp < 3)

{

//printf("tmp = %d\n", tmp);

if (tmp >= data_len)

{

break;

}

prepare = ((prepare << 8) | (data[tmp] & 0xFF));

tmp++;

temp++;

}

prepare = (prepare<

//printf("before for : temp = %d, prepare = %d\n", temp, prepare);

for (i = 0; i < 4 ;i++ )

{

if (temp < i)

{

changed[i] = 0x40;

}

else

{

changed[i] = (prepare>>((3-i)*6)) & 0x3F;

}

*f = base[changed[i]];

//printf("%.2X", changed[i]);

f++;

}

}

*f = '\0';

return ret;

}

/* out_len 解码后的数据长度 */

char *CryptObject::base64_decode(const char *data, int data_len, int &out_len)

{

int ret_len = (data_len / 4) * 3;

int equal_count = 0;

char *ret = NULL;

char *f = NULL;

int tmp = 0;

int temp = 0;

char need[3];

int prepare = 0;

int i = 0;

if (*(data + data_len - 1) == '=')

{

equal_count += 1;

}

if (*(data + data_len - 2) == '=')

{

equal_count += 1;

}

if (*(data + data_len - 3) == '=')

{//seems impossible

equal_count += 1;

}

switch (equal_count)

{

case 0:

ret_len += 4;//3 + 1 [1 for NULL]

break;

case 1:

ret_len += 4;//Ceil((6*3)/8)+1

break;

case 2:

ret_len += 3;//Ceil((6*2)/8)+1

break;

case 3:

ret_len += 2;//Ceil((6*1)/8)+1

break;

}

ret = (char *)malloc(ret_len);

if (ret == NULL)

{

printf("No enough memory.\n");

exit(0);

}

memset(ret, 0, ret_len);

f = ret;

while (tmp < (data_len - equal_count))

{

temp = 0;

prepare = 0;

memset(need, 0, 3);

while (temp < 4)

{

if (tmp >= (data_len - equal_count))

{

break;

}

prepare = (prepare << 6) | (find_pos(data[tmp]));

temp++;

tmp++;

}

prepare = prepare << ((4-temp) * 6);

for (i=0; i<3 ;i++ )

{

if (i == temp)

{

break;

}

*f = (char)((prepare>>((2-i)*8)) & 0xFF);

f++;

}

}

*f = '\0';

out_len = (int)(f - ret);

if (out_len < 0) out_len = 0;

return ret;

}

你可能感兴趣的:(java,cbc加密php)