工作中遇到了安全传输问题,需要解决iOS和Android客户端跟java服务端的安全传输问题,结合对HTTPS的了解,便使用DES+RSA方式模拟HTTPS。在实现过程中,遇到了一些瓶颈,主要是保持平台兼容性的问题,Android和服务的还可以,统一使用java API,但要包含iOS就比较麻烦了,参考了网上很多资料,忙了三四天,终于搞通了。
瓶颈卡在用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推荐
  • —软件人才免语言低担保 赴美带薪读研!—



更多相关文章

  1. Android Basic-xml的数据读取及保存
  2. android文件系统及其制作
  3. Android中如何反编译apk文件
  4. Android平台上如何让应用程序获得系统权限以及如何使用platform
  5. android 使用https请求请求数据
  6. Android多媒体--访问网络上的Audio对应的M3U文件,实现网络音频流
  7. 文件操作二
  8. Android使用Itext生成pdf文件

随机推荐

  1. List of Android(安卓)MIME types and Ur
  2. Android中使用Junit测试框架
  3. Android获取长按按键响应
  4. Android(安卓)系统架构
  5. Android视图篇之一:Android常见基本布局
  6. Android应用开发相关下载资源(2013/03/22
  7. Android(安卓)error: Failed to install
  8. Android的Notification研究
  9. Android(安卓)UI设计系统-android select
  10. Android学习笔记之mainfest文件中android