iOS、Android、java服务端 DES+RSA安全传输统一实现

2 篇文章 0 订阅
1 篇文章 0 订阅
工作中遇到了安全传输问题,需要解决iOS和Android客户端跟java服务端的安全传输问题,结合对HTTPS的了解,便使用DES+RSA方式模拟HTTPS。在实现过程中,遇到了一些瓶颈,主要是保持平台兼容性的问题,Android和服务的还可以,统一使用java API,但要包含iOS就比较麻烦了,参考了网上很多资料,忙了三四天,终于搞通了。 :cry:
瓶颈卡在用openssl生成的pem文件在java没找到合适的API来解析获取私钥,最后是参考网上资料用openssl命令将pem文件转换为pkcs8格式文件才能读取。

Mac OS上执行openssl命令操作

1)创建私钥
openssl genrsa -out private_key.pem 1024
2)创建证书请求(按照提示输入信息)
openssl req -new -out cert.csr -key private_key.pem
3)自签署根证书
openssl x509 -req -in cert.csr -out public_key.der -outform der -signkey private_key.pem -days 3650
4)用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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值