欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-06-15 13:17:42
...
工作中遇到了安全传输问题,需要解决iOS和Android客户端跟java服务端的安全传输问题,结合对HTTPS的了解,便使用DES+RSA方式模拟HTTPS。在实现过程中,遇到了一些瓶颈,主要是保持平台兼容性的问题,Android和服务的还可以,统一使用java API,但要包含iOS就比较麻烦了,参考了网上很多资料,忙了三四天,终于搞通了。iOS、Android、java服务端 DES+RSA安全传输统一实现
            
    
    博客分类: androidiosDES安全传输JavaRSA iosandroidjavaDESRSA
瓶颈卡在用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