iOS、Android、java服务端 DES+RSA安全传输统一实现
16lz
2021-01-23
工作中遇到了安全传输问题,需要解决iOS和Android客户端跟java服务端的安全传输问题,结合对HTTPS的了解,便使用DES+RSA方式模拟HTTPS。在实现过程中,遇到了一些瓶颈,主要是保持平台兼容性的问题,Android和服务的还可以,统一使用java API,但要包含iOS就比较麻烦了,参考了网上很多资料,忙了三四天,终于搞通了。
瓶颈卡在用openssl生成的pem文件在java没找到合适的API来解析获取私钥,最后是参考网上资料用openssl命令将pem文件转换为pkcs8格式文件才能读取。
Mac OS上执行openssl命令操作
Android及java调用API
iOS调用API(其中有网上直接copy来的代码,在此多谢网友分享)
参考网址:
http://blog.iamzsx.me/show.html?id=155002
http://shuany.iteye.com/blog/730910
已有 1 人发表留言,猛击->> 这里<<-参与讨论
ITeye推荐
瓶颈卡在用openssl生成的pem文件在java没找到合适的API来解析获取私钥,最后是参考网上资料用openssl命令将pem文件转换为pkcs8格式文件才能读取。
Mac OS上执行openssl命令操作
1)创建私钥openssl genrsa -out private_key.pem 10242)创建证书请求(按照提示输入信息)openssl req -new -out cert.csr -key private_key.pem3)自签署根证书openssl x509 -req -in cert.csr -out public_key.der -outform der -signkey private_key.pem -days 36504)用java代码要从这个文件中得到想要的priavtekey 可以先用命令(就被这东西卡住了)openssl pkcs8 -topk8 -inform PEM -outform DER -in private_key.pem -out private_pkcs8_der.key -nocrypt
Android及java调用API
import java.io.ByteArrayOutputStream;import java.io.FileInputStream;import java.math.BigInteger;import java.security.Key;import java.security.KeyFactory;import java.security.KeyPair;import java.security.KeyPairGenerator;import java.security.PrivateKey;import java.security.PublicKey;import java.security.cert.Certificate;import java.security.cert.CertificateFactory;import java.security.interfaces.RSAPrivateKey;import java.security.interfaces.RSAPublicKey;import java.security.spec.PKCS8EncodedKeySpec;import java.util.HashMap;import javax.crypto.Cipher;import javax.crypto.SecretKey;import javax.crypto.SecretKeyFactory;import javax.crypto.spec.DESKeySpec;import sun.misc.BASE64Decoder;import sun.misc.BASE64Encoder;public class Crypt {static BASE64Decoder decoder = new BASE64Decoder();static BASE64Encoder encoder = new BASE64Encoder(); static String DES = "DES"; static String RSA = "RSA"; static String encode = "UTF-8";//保持平台兼容统一使用utf-8 //私钥文件路径 static String privateFile = "/XXX/private_pkcs8_der.key"; //公钥文件路径 static String publicFile = "/XXX/public_key.der";//des 加密 private static byte [] encryptByteDES(byte[] byteD,String strKey) throws Exception { return doEncrypt(byteD, getKey(strKey), DES); } //des 解密 private static byte [] decryptByteDES(byte[] byteD,String strKey) throws Exception { return doDecrypt(byteD, getKey(strKey), DES); } public static SecretKey getKey(String strKey) throws Exception {DESKeySpec desKeySpec = new DESKeySpec(strKey.getBytes());SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);SecretKey sk = keyFactory.generateSecret(desKeySpec);return sk;} //pkcs8_der.key文件为私钥 只能保存在服务端 //public_key.der为公钥文件,保存在客户端public static void main(String[] args) throws Exception {String text = "ceshishuuju测试数据ceshishuuju测试数据";String pwd="12345678";//客户端加密HashMap<String, String> data = DESAndRSAEncrypt(text.getBytes(encode),pwd);System.out.println("pwd RSA加密后base64:"+data.get("key"));System.out.println("text DES加密后base64:"+data.get("data"));//服务端解密String textDecrypt = DESAndRSADecrypt(data);System.out.println("未处理原文:"+text);System.out.println("解密后数据:"+textDecrypt);//generateKeyPair();}//客户端加密static HashMap<String, String> DESAndRSAEncrypt(byte[] dataToEncypt,String pwd) throws Exception{byte[] encryptData = encryptByteDES(dataToEncypt, pwd);String dataBase64 = encoder.encode(encryptData);byte[] encryptKey = RSAEncrypt(pwd.getBytes(encode));String keyBase64 = encoder.encode(encryptKey);HashMap<String, String> data = new HashMap<String, String>();data.put("data", dataBase64);data.put("key", keyBase64);return data;}//服务端解密static String DESAndRSADecrypt(HashMap<String, String> data) throws Exception {String dataBase64 = data.get("data");String keyBase64 = data.get("key");byte[] encryptedData = decoder.decodeBuffer(dataBase64);byte[] encryptedKey = decoder.decodeBuffer(keyBase64);byte[] decryptedKey= RSADecrypt(encryptedKey);String pwd = new String(decryptedKey,encode);System.out.println("DES密码:"+pwd);byte[] decryptedData = decryptByteDES(encryptedData, pwd);String textDecrypt = new String(decryptedData,encode);return textDecrypt;}//公钥加密 public static byte[] RSAEncrypt(byte[] plainText) throws Exception{//读取公钥CertificateFactory certificatefactory = CertificateFactory.getInstance("X.509");FileInputStream bais = new FileInputStream(publicFile);Certificate cert = certificatefactory.generateCertificate(bais);bais.close();PublicKey puk = cert.getPublicKey();//System.out.println("公钥base64:"+encoder.encode(puk.getEncoded()));return doEncrypt(plainText, puk, RSA);}//私钥解密public static byte[] RSADecrypt(byte[] encryptData) throws Exception{FileInputStream in = new FileInputStream(privateFile);ByteArrayOutputStream bout = new ByteArrayOutputStream();byte[] tmpbuf = new byte[1024];int count = 0;while ((count = in.read(tmpbuf)) != -1) {bout.write(tmpbuf, 0, count);}in.close();//读取私钥KeyFactory keyFactory = KeyFactory.getInstance(RSA);PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(bout.toByteArray());PrivateKey prk = keyFactory.generatePrivate(privateKeySpec);//System.out.println("私钥base64:"+encoder.encode(prk.getPrivateExponent().toByteArray()));return doDecrypt(encryptData, prk, RSA);}/** * 执行加密操作 * @param data 待操作数据 * @param key Key * @param type 算法 RSA or DES * @return * @throws Exception */public static byte[] doEncrypt(byte[] data,Key key,String type) throws Exception{Cipher cipher = Cipher.getInstance(type);cipher.init(Cipher.ENCRYPT_MODE, key);return cipher.doFinal(data);}/** * 执行解密操作 * @param data 待操作数据 * @param key Key * @param type 算法 RSA or DES * @return * @throws Exception */public static byte[] doDecrypt(byte[] data,Key key,String type) throws Exception{Cipher cipher = Cipher.getInstance(type);cipher.init(Cipher.DECRYPT_MODE, key);return cipher.doFinal(data);}public static void generateKeyPair() throws Exception{KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA);kpg.initialize(1024); // 指定密钥的长度,初始化密钥对生成器KeyPair kp = kpg.generateKeyPair(); // 生成密钥对RSAPublicKey puk = (RSAPublicKey) kp.getPublic();RSAPrivateKey prk = (RSAPrivateKey) kp.getPrivate();BigInteger e = puk.getPublicExponent();BigInteger n = puk.getModulus();BigInteger d = prk.getPrivateExponent();BASE64Encoder encoder = new BASE64Encoder();System.out.println("public key:\n"+encoder.encode(n.toByteArray()));System.out.println("private key:\n"+encoder.encode(d.toByteArray()));}}
iOS调用API(其中有网上直接copy来的代码,在此多谢网友分享)
#import <Foundation/Foundation.h>@interface WDCrypto : NSObject/* * DES加密数据 RSA加密DES密钥 公钥证书路径(默认mainBundle下 public_key.der) * 返回加密后数据base64编码 {key:xxx,data:XXX} */+(NSDictionary*)encryptWithDESAndRSA:(NSData*) data withKey:(NSString*)key keyPath:(NSString*)keyPath;/* * RSA加密 输入NSString类型数据 公钥证书路径(默认mainBundle下 public_key.der) * 返回加密后数据base64编码 */+(NSString*)RSAEncryptData:(NSString*)text keyPath:(NSString*)keyPath;/* * RSA加密 输入NSString类型数据 公钥证书路径(默认mainBundle下 public_key.der) * 返回加密后数据base64编码 */+(NSData*)RSAEncryptToData:(NSString*)text keyPath:(NSString*)keyPath;/* * DES加密 输入NSString类型数据和NSString加密密钥 返回加密后数据base64编码 */+(NSString*)DESEncryptWithBase64:(NSString*)str key:(NSString*)key;/* * DES加密 输入密文base64和NSString解密密钥 返回解密后数据明文 */+(NSString*)DESDecryptBase64:(NSString*)base64 key:(NSString*)key;/* * DES加密 输入NSData类型数据和NSString加密密钥 返回加密后数据 */+(NSData *)DESEncrypt:(NSData *)data WithKey:(NSString *)key;/* * DES加密 输入NSData类型密文和NSString解密密钥 返回解密后数据 */+(NSData *)DESDecrypt:(NSData *)data WithKey:(NSString *)key;@end/* * RSA加密 公钥文件默认为public_key.der */@interface WDRSACrypt : NSObject { SecKeyRef publicKey; SecCertificateRef certificate; SecPolicyRef policy; SecTrustRef trust; size_t maxPlainLen;}/* *指定证书路径 */- (id)initWithKeyPath:(NSString*) publicKeyPath;- (NSData *) encryptWithData:(NSData *)content;- (NSData *) encryptWithString:(NSString *)content;@end
#import "WDCrypto.h"#import <CommonCrypto/CommonCryptor.h>@implementation WDCrypto//客户端加密+(NSDictionary*)encryptWithDESAndRSA:(NSData*) data withKey:(NSString*)key keyPath:(NSString*)keyPath{ //rsa NSString* encryptedKey = [WDCrypto RSAEncryptData:key keyPath:keyPath]; //des NSData* encryptedData = [WDCrypto DESEncrypt:data WithKey:key]; NSString* encryptedBase64 = [encryptedData base64Encoding]; NSDictionary* dict = [[NSDictionary alloc] initWithObjectsAndKeys:encryptedKey,@"key",encryptedBase64,@"data",nil]; return dict;}+(NSString*)RSAEncryptData:(NSString*)text keyPath:(NSString*)keyPath{ NSData* data = [WDCrypto RSAEncryptToData:text keyPath:keyPath]; NSString* encryptedKey = [data base64Encoding]; return encryptedKey;}+(NSData*)RSAEncryptToData:(NSString*)text keyPath:(NSString*)keyPath{ NSData* encryptData = nil; if (!keyPath) { keyPath = [[NSBundle mainBundle] pathForResource:@"public_key" ofType:@"der"]; } WDRSACrypt *rsa = [[WDRSACrypt alloc] initWithKeyPath:keyPath]; if (rsa != nil) { encryptData = [rsa encryptWithString:text]; }else { NSLog(@"init rsa error"); } return encryptData;}+(NSString*)DESEncryptWithBase64:(NSString*)str key:(NSString*)key{ NSData* data = [str dataUsingEncoding:(NSUTF8StringEncoding)]; NSData* encryptData = [WDCrypto DESEncrypt:data WithKey:key]; NSString* base64 = [encryptData base64Encoding]; return base64;}+(NSString*)DESDecryptBase64:(NSString*)base64 key:(NSString*)key{ NSData* encryptData = [[NSData alloc] initWithBase64Encoding:base64]; NSData* data = [WDCrypto DESDecrypt:encryptData WithKey:key]; NSString* decryptStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; return decryptStr;}/****************************************************************************** 函数名称 : + (NSData *)DESEncrypt:(NSData *)data WithKey:(NSString *)key 函数描述 : 文本数据进行DES加密 输入参数 : (NSData *)data (NSString *)key 输出参数 : N/A 返回参数 : (NSData *) 备注信息 : 此函数不可用于过长文本 ******************************************************************************/+ (NSData *)DESEncrypt:(NSData *)data WithKey:(NSString *)key{ char keyPtr[kCCKeySizeAES256+1]; bzero(keyPtr, sizeof(keyPtr)); [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; NSUInteger dataLength = [data length]; size_t bufferSize = dataLength + kCCBlockSizeAES128; void *buffer = malloc(bufferSize); size_t numBytesEncrypted = 0; CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmDES, kCCOptionPKCS7Padding | kCCOptionECBMode, keyPtr, kCCBlockSizeDES, NULL, [data bytes], dataLength, buffer, bufferSize, &numBytesEncrypted); if (cryptStatus == kCCSuccess) { return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; } free(buffer); return nil;}/****************************************************************************** 函数名称 : + (NSData *)DESEncrypt:(NSData *)data WithKey:(NSString *)key 函数描述 : 文本数据进行DES解密 输入参数 : (NSData *)data (NSString *)key 输出参数 : N/A 返回参数 : (NSData *) 备注信息 : 此函数不可用于过长文本 ******************************************************************************/+ (NSData *)DESDecrypt:(NSData *)data WithKey:(NSString *)key{ char keyPtr[kCCKeySizeAES256+1]; bzero(keyPtr, sizeof(keyPtr)); [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; NSUInteger dataLength = [data length]; size_t bufferSize = dataLength + kCCBlockSizeAES128; void *buffer = malloc(bufferSize); size_t numBytesDecrypted = 0; CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmDES, kCCOptionPKCS7Padding | kCCOptionECBMode, keyPtr, kCCBlockSizeDES, NULL, [data bytes], dataLength, buffer, bufferSize, &numBytesDecrypted); if (cryptStatus == kCCSuccess) { return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted]; } free(buffer); return nil;}@end@implementation WDRSACrypt- (id)initWithKeyPath:(NSString*) publicKeyPath{ self = [super init]; if (publicKeyPath == nil) { NSLog(@"Can not find pub.der"); return nil; } NSData *publicKeyFileContent = [NSData dataWithContentsOfFile:publicKeyPath]; if (publicKeyFileContent == nil) { NSLog(@"Can not read from pub.der"); return nil; } certificate = SecCertificateCreateWithData(kCFAllocatorDefault, ( __bridge CFDataRef)publicKeyFileContent); if (certificate == nil) { NSLog(@"Can not read certificate from pub.der"); return nil; } policy = SecPolicyCreateBasicX509(); OSStatus returnCode = SecTrustCreateWithCertificates(certificate, policy, &trust); if (returnCode != 0) { NSLog(@"SecTrustCreateWithCertificates fail. Error Code: %ld", returnCode); return nil; } SecTrustResultType trustResultType; returnCode = SecTrustEvaluate(trust, &trustResultType); if (returnCode != 0) { NSLog(@"SecTrustEvaluate fail. Error Code: %ld", returnCode); return nil; } publicKey = SecTrustCopyPublicKey(trust); if (publicKey == nil) { NSLog(@"SecTrustCopyPublicKey fail"); return nil; } maxPlainLen = SecKeyGetBlockSize(publicKey) - 12; return self;}- (NSData *) encryptWithData:(NSData *)content { size_t plainLen = [content length]; if (plainLen > maxPlainLen) { NSLog(@"content(%ld) is too long, must < %ld", plainLen, maxPlainLen); return nil; } void *plain = malloc(plainLen); [content getBytes:plain length:plainLen]; size_t cipherLen = 128; // 当前RSA的密钥长度是128字节 void *cipher = malloc(cipherLen); OSStatus returnCode = SecKeyEncrypt(publicKey, kSecPaddingPKCS1, plain, plainLen, cipher, &cipherLen); NSData *result = nil; if (returnCode != 0) { NSLog(@"SecKeyEncrypt fail. Error Code: %ld", returnCode); } else { result = [NSData dataWithBytes:cipher length:cipherLen]; } free(plain); free(cipher); return result;}- (NSData *) encryptWithString:(NSString *)content { return [self encryptWithData:[content dataUsingEncoding:NSUTF8StringEncoding]];}- (void)dealloc{ CFRelease(certificate); CFRelease(trust); CFRelease(policy); CFRelease(publicKey);}@end
参考网址:
http://blog.iamzsx.me/show.html?id=155002
http://shuany.iteye.com/blog/730910
已有 1 人发表留言,猛击->> 这里<<-参与讨论
ITeye推荐
- —软件人才免语言低担保 赴美带薪读研!—
更多相关文章
- Android Basic-xml的数据读取及保存
- android文件系统及其制作
- Android中如何反编译apk文件
- Android平台上如何让应用程序获得系统权限以及如何使用platform
- android 使用https请求请求数据
- Android多媒体--访问网络上的Audio对应的M3U文件,实现网络音频流
- 文件操作二
- Android使用Itext生成pdf文件