android、ios与服务器端php使用rsa加密解密通讯

分类: Android/OMS 968人阅读 评论(0) 收藏 举报

目录(?)[+]

转自:http://blog.csdn.net/lx923988898/article/details/10374145

下载RSA密钥生成工具openssl,点击下载,解压缩至独立的文件夹,进入其中的bin目录,执行以下命令:
1 2 3 4 5 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
第一条命令生成原始 RSA私钥文件 rsa_private_key.pem,第二条命令将原始 RSA私钥转换为 pkcs8格式,第三条生成RSA公钥 rsa_public_key.pem
从上面看出通过私钥能生成对应的公钥,因此我们将私钥private_key.pem用在服务器端,公钥发放给android跟ios等前端

第二步,php服务器端,使用openssl方法来进行加密解密类,代码如下:

<?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; } } ?>
打开private_key.pem,将上面的$PRIVATE_KEY,替换成private_key.pem的内容即可,服务器端我们只需要使用私钥来加密解密。

第三步,android前端,使用java的Cipher类来实现加密解密类,代码如下:

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 ; } } }
需要注意的是,在初始化Cipher对象时,一定要指明使用"RSA/ECB/PKCS1Padding"格式如Cipher.getInstance("RSA/ECB/PKCS1Padding");
打开rsa_public_key.pem文件,将上面代码的RSA_PUBLICE替换成其中内容即可。

第四步,ios前端,iOS上没有直接处理RSA加密的API,网上说的大多数也是处理X.509的证书的方法来实现,不过X.509证书是带签名的,在php端openssl_pkey_get_private方法获取密钥时,第二个参数需要传签名,而android端实现X.509证书加密解密较为不易,在这里我们利用ios兼容c程序的特点,利用openssl的api实现rsa的加密解密,代码如下:

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

CRSA.m代码

#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
其中openssl api包,我们可以在第一步RSA密钥生成工具openssl的include文件夹中得到,完整代码包请点击这里下载

更多相关文章

  1. Android之——代码混淆
  2. Android源代码下载指南(图解)
  3. Android客户端向服务器端发送数据的流程(1)
  4. Android系统进程Zygote启动过程的源代码分析
  5. Android布局--相对布局,RTL,用代码实现布局
  6. Android:高效的Android代码编写
  7. webkit framework for android 4.0.3 代码总结

随机推荐

  1. Android自动挂断来电(ITelephony的使用)
  2. 【Android(安卓)Developers Training】 6
  3. 谷歌CTS测试之GTS测试简介
  4. Android(安卓)如何添加一种锁屏方式
  5. MTK Android(安卓)P 开机无动画,无铃声问
  6. Unity2018下Android(安卓)SDK设置
  7. Android(安卓)解析Json
  8. Android(安卓)Studio之项目突然出现乱码
  9. Android(安卓)开发技术周报 Issue#290
  10. android 动态注册JNI函数过程源码分析