项目中需要用到加密通讯,因为服务器是用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<<((3-temp)*8)); //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; }
正在研究这方面算法 能发我一份吗 谢谢!1252143465@qq.com
能不能给我发一份源码,谢谢,我也再搞三个平台的加解密,万分感谢啊
涛,你的完整代码可以发给我下吗?最近搞三个平台这个问题有点儿恼火呀。573903502@qq.com
@于晓龙 已发
博主,我用java进行aes(cbc)加密,c++就是解不了,发我一份被,谢谢了
1429547908@qq.com
@谢林 @nico @张杰 已发
好不容易看到这么好的东东,能不能发我一份呀。热盼呀。… network20001@163.com,多谢呀。
博主,您好,配套的完整代码能发一份给我吗?我的邮箱是 541107874@qq.com 谢谢
博主,您好,配套的完整代码能发一份给我吗?
能给我发一份吗, 908211420@qq.com
@陈伟 @chen @龙就 @oe 已发
博主,您好,PHP和C++的完整代码能发一份给我吗?
邮箱是:1031825526@qq.com
非常感谢!
涛哥,AES CBC 加解密 Java/PHP/C++ 能发一份源码给我么,228026607@qq.com, 主要是php和c++互通的完整源码,谢谢
你好,AES CBC 相互加解密 Java/PHP/C++ 能发一份源码给我么,2603529478@qq.com, 主要是php和c++互通的完整源码,,谢谢
博主,您好,PHP和C++的完整代码能发一份给我吗?
邮箱是:onages@sina.com
非常感谢!
博主,您好,配套的完整代码能发一份给我吗?邮箱是:285920192@qq.com。非常感谢!
@夏周全 @Yu 已发
博主,您好,我最近也在搞类似的东西,遇到了一些问题,可以发送一份完整的代码吗?邮箱是:554872164@qq.com。非常感谢!
你好,AES CBC 相互加解密 Java/PHP/C++ 能发一份源码给我么,852784647@qq.com, 主要是php和c++互通的完整源码,,谢谢
@Zhang 抱歉,一直没看评论,已经发了。
涛,,我也遇到了这方面的问题,AES CBC 相互加解密 Java/PHP/C++ 能发一份源码给我么,1281635271@qq.com, 主要是php和c++互通,,c++使用的是哪个加密库,谢谢
已经发了:)
涛,你的 C++ AES加密和PHP解密的配套的完整的代码能发一份给我吗? 我的邮箱是 flydish#gmail.com