http://alunblog.duapp.com/?p=50
点击打开链接
最近做手机项目,服务器端使用的是php,客户端分别有android版及ios版,在部分通讯环节需要对内容进行加密,RSA加密演算法是一种非对称加密演算法,能够较好达到要求,不过如果服务器架设https服务,较为麻烦,系统效率也不高,我们只需要在部分重要接口上使用RSA加密解密就行。
openssl genrsa -out rsa_private_key.pem 1024 openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out private_key.pem openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
<?php /** * @author alun (http://alunblog.duapp.com) * @version 1.0 * @created 2013-5-17 */ class Rsa { private static $PRIVATE_KEY = '-----BEGIN PRIVATE KEY----- MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAM9nUm7rPNhSgvsd jMuCd5E7IMJB/80A1YY7jYV9fBCKdhVKmqea26QYuw6FW7B00fppEUTSazduSmn9 Yvhx9UOCcI75b0nq9FWm5O4P+Kp8l31M1pwsJ3cm+DceGOrFsl47vh9idiqj+abI lJ4sTmJmDghmbks9YFlZSndQsIBlAgMBAAECgYAasa6vbgF3yi7niScc7l7bR2Pw /LOivA+/ZhzR6JO2QUvvc5myJsFMPo6c0Nc7P93iv/EkDX0VNlHHkIBTf79URHXM gXwMad4pHAeOiqxk5A9w/szDCBoETngtoqQGJq+QINxwPVvDEO4i224Uj3MKg2fo 4SDy3P1GCAAj1ahNoQJBAP4FV9vLWdLOOwOLnBpXt6vru4HT5VIf9fCeBIemuQ4C /yRtgU38zXWgZ8AAmS6EjBEUDnN/tWid6UBKfgPDwAkCQQDRBP+Y9wIYIaSxeL7B nHhPT25yAJCGK+l6r2qeaHVQr81O9YjusEi8E2M5OxCRolKxC3L7hrLJX8z1oyOV dNx9AkBqYGhzpgv+qNiz2mJL8dH8ECMc8lTFeJbw5eu1tw8mHAEnCyisNSMBkGQC Vv3PKjjR6hlHKwMYRZDpmIh/IRmpAkEAr1soLGaeZSxkhVetgbUJ4k/bct0yYr4Y ZQshwcAVHBpBforT1JwkiVUim3MIFYY/JbVbQ9XfzL4Ir9OsGMkv6QJAPaQnyNY5 /D0PhXqODOM6jtAHHRfaSi4gve6AZ0iRz6YlB8beJ1ywZaJZWD9Cuw3zy4dDpCOn A4tBsIdpMMoT+w== -----END PRIVATE KEY-----'; /** *返回对应的私钥 */ private static function getPrivateKey(){ $privKey = self::$PRIVATE_KEY; return openssl_pkey_get_private($privKey); } /** * 私钥加密 */ public static function privEncrypt($data) { if(!is_string($data)){ return null; } return openssl_private_encrypt($data,$encrypted,self::getPrivateKey())? base64_encode($encrypted) : null; } /** * 私钥解密 */ public static function privDecrypt($encrypted) { if(!is_string($encrypted)){ return null; } return (openssl_private_decrypt(base64_decode($encrypted), $decrypted, self::getPrivateKey()))? $decrypted : null; } } ?>
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.spec.X509EncodedKeySpec; import javax.crypto.Cipher; import android.util.Base64; /** * @author alun (http://alunblog.duapp.com) * @version 1.0 * @created 2013-5-17 */ public class Rsa { private static final String RSA_PUBLICE = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDPZ1Ju6zzYUoL7HYzLgneROyDC" + "\r" + "Qf/NANWGO42FfXwQinYVSpqnmtukGLsOhVuwdNH6aRFE0ms3bkpp/WL4cfVDgnCO" + "\r" + "+W9J6vRVpuTuD/iqfJd9TNacLCd3Jvg3HhjqxbJeO74fYnYqo/mmyJSeLE5iZg4I" + "\r" + "Zm5LPWBZWUp3ULCAZQIDAQAB"; private static final String ALGORITHM = "RSA"; /** * 得到公钥 * @param algorithm * @param bysKey * @return */ private static PublicKey getPublicKeyFromX509(String algorithm, String bysKey) throws NoSuchAlgorithmException, Exception { byte[] decodedKey = Base64.decode(bysKey,Base64.DEFAULT); X509EncodedKeySpec x509 = new X509EncodedKeySpec(decodedKey); KeyFactory keyFactory = KeyFactory.getInstance(algorithm); return keyFactory.generatePublic(x509); } /** * 使用公钥加密 * @param content * @param key * @return */ public static String encryptByPublic(String content) { try { PublicKey pubkey = getPublicKeyFromX509(ALGORITHM, RSA_PUBLICE); Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, pubkey); byte plaintext[] = content.getBytes("UTF-8"); byte[] output = cipher.doFinal(plaintext); String s = new String(Base64.encode(output,Base64.DEFAULT)); return s; } catch (Exception e) { return null; } } /** * 使用公钥解密 * @param content 密文 * @param key 商户私钥 * @return 解密后的字符串 */ public static String decryptByPublic(String content) { try { PublicKey pubkey = getPublicKeyFromX509(ALGORITHM, RSA_PUBLICE); Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, pubkey); InputStream ins = new ByteArrayInputStream(Base64.decode(content,Base64.DEFAULT)); ByteArrayOutputStream writer = new ByteArrayOutputStream(); byte[] buf = new byte[128]; int bufl; while ((bufl = ins.read(buf)) != -1) { byte[] block = null; if (buf.length == bufl) { block = buf; } else { block = new byte[bufl]; for (int i = 0; i < bufl; i++) { block[i] = buf[i]; } } writer.write(cipher.doFinal(block)); } return new String(writer.toByteArray(), "utf-8"); } catch (Exception e) { return null; } } }
CRSA.h代码:
#import <Foundation/Foundation.h> #include <openssl/rsa.h> #include <openssl/pem.h> #include <openssl/err.h> typedef enum { KeyTypePublic, KeyTypePrivate }KeyType; typedef enum { RSA_PADDING_TYPE_NONE = RSA_NO_PADDING, RSA_PADDING_TYPE_PKCS1 = RSA_PKCS1_PADDING, RSA_PADDING_TYPE_SSLV23 = RSA_SSLV23_PADDING }RSA_PADDING_TYPE; @interface CRSA : NSObject{ RSA *_rsa; } + (id)shareInstance; - (BOOL)importRSAKeyWithType:(KeyType)type; - (int)getBlockSizeWithRSA_PADDING_TYPE:(RSA_PADDING_TYPE)padding_type; - (NSString *) encryptByRsa:(NSString*)content withKeyType:(KeyType)keyType; - (NSString *) decryptByRsa:(NSString*)content withKeyType:(KeyType)keyType; @end
#import "CRSA.h" #define BUFFSIZE 1024 #import "Base64.h" #define PADDING RSA_PADDING_TYPE_PKCS1 @implementation CRSA + (id)shareInstance { static CRSA *_crsa = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _crsa = [[self alloc] init]; }); return _crsa; } - (BOOL)importRSAKeyWithType:(KeyType)type { FILE *file; NSString *keyName = type == KeyTypePublic ? @"public_key" : @"private_key"; NSString *keyPath = [[NSBundle mainBundle] pathForResource:keyName ofType:@"pem"]; file = fopen([keyPath UTF8String], "rb"); if (NULL != file) { if (type == KeyTypePublic) { _rsa = PEM_read_RSA_PUBKEY(file, NULL, NULL, NULL); assert(_rsa != NULL); } else { _rsa = PEM_read_RSAPrivateKey(file, NULL, NULL, NULL); assert(_rsa != NULL); } fclose(file); return (_rsa != NULL) ? YES : NO; } return NO; } - (NSString *) encryptByRsa:(NSString*)content withKeyType:(KeyType)keyType { if (![self importRSAKeyWithType:keyType]) return nil; int status; int length = [content length]; unsigned char input[length + 1]; bzero(input, length + 1); int i = 0; for (; i < length; i++) { input[i] = [content characterAtIndex:i]; } NSInteger flen = [self getBlockSizeWithRSA_PADDING_TYPE:PADDING]; char *encData = (char*)malloc(flen); bzero(encData, flen); switch (keyType) { case KeyTypePublic: status = RSA_public_encrypt(length, (unsigned char*)input, (unsigned char*)encData, _rsa, PADDING); break; default: status = RSA_private_encrypt(length, (unsigned char*)input, (unsigned char*)encData, _rsa, PADDING); break; } if (status) { NSData *returnData = [NSData dataWithBytes:encData length:status]; free(encData); encData = NULL; NSString *ret = [returnData base64EncodedString]; return ret; } free(encData); encData = NULL; return nil; } - (NSString *) decryptByRsa:(NSString*)content withKeyType:(KeyType)keyType { if (![self importRSAKeyWithType:keyType]) return nil; int status; NSData *data = [content base64DecodedData]; int length = [data length]; NSInteger flen = [self getBlockSizeWithRSA_PADDING_TYPE:PADDING]; char *decData = (char*)malloc(flen); bzero(decData, flen); switch (keyType) { case KeyTypePublic: status = RSA_public_decrypt(length, (unsigned char*)[data bytes], (unsigned char*)decData, _rsa, PADDING); break; default: status = RSA_private_decrypt(length, (unsigned char*)[data bytes], (unsigned char*)decData, _rsa, PADDING); break; } if (status) { NSMutableString *decryptString = [[NSMutableString alloc] initWithBytes:decData length:strlen(decData) encoding:NSASCIIStringEncoding]; free(decData); decData = NULL; return decryptString; } free(decData); decData = NULL; return nil; } - (int)getBlockSizeWithRSA_PADDING_TYPE:(RSA_PADDING_TYPE)padding_type { int len = RSA_size(_rsa); if (padding_type == RSA_PADDING_TYPE_PKCS1 || padding_type == RSA_PADDING_TYPE_SSLV23) { len -= 11; } return len; } @end