【转】iOS下使用RSA算法与PHP进行加解密通讯

By | 03月04日
Advertisement

首先了解一下几个相关概念,以方便后面遇到的问题的解决:

  • RSA算法:1977年由Ron Rivest、Adi Shamirh和LenAdleman发明的,RSA就是取自他们三个人的名字。算法基于一个数论:将两个大素数相乘非常容易,但要对这个乘积的结果进行因式分解却非常困难,因此可以把乘积公开作为公钥。该算法能够抵抗目前已知的所有密码攻击。RSA算法是一种非对称算法,算法需要一对密钥,使用其中一个加密,需要使用另外一个才能解密。我们在进行RSA加密通讯时,就把公钥放在客户端,私钥留在服务器。
  • DER, PEM:既然使用RSA需要一对密钥,那么我们当然是要先使用工具来生成这样一对密钥了。在linux、unix下,最简单方便的就是使用openssl命令行了。而DER、PEM就是生成的密钥可选择的两种文件格式。DER是Distinguished Encoding Rules的简称,是一种信息传输语法规则,在ITU X.690中定义的。在ios端,我们的公钥就是需要这样一种格式的,我们可以从Certificate, Key, and Trust Services Reference这篇文档的SecCertificateCreateWithData函数的data参数的说明中看到。而PEM格式是一种对DER进行封装的格式,他只是把der的内容进行了base64编码并加上了头尾说明。openssl命令行默认输出的都是PEM格式的文件,要能够在ios下使用,我们需要指定使用DER或者先生成PEM然后转换称DER。

使用openssl命令行生成密钥对

openssl req -x509 -out public_key.der -outform der -new -newkey rsa:1024 -keyout private_key.pem

按照提示,填入私钥的密码,签名证书的组织名、邮件等信息之后,就会生成包含有公钥的证书文件public_key.der合私钥文件private_key.pem。public_key.der文件用于分发到ios客户端进行公钥加解密,而private_key.pem文件留在服务器端供php使用。当然,如果为了在服务器端进行加解密测试,那么我们还可以生成一个服务器端PHP使用的pem公钥文件:

openssl rsa -in private_key.pem -pubout -out public_key.pem

上面这个命令就会根据输入的私钥文件生成pem格式的公钥文件了。从这里也可以看到,根据私钥,我们是可以生成相对应的公钥的,这也就是为什么我们要把公钥放在客户端,而不是私钥放在客户端的原因了。服务器端PHP的加解密函数闲话不多说,贴一段代码,肯定能看懂的了

class RSAEncryptTest {    const PRIVATE_KEY = "-----BEGIN ENCRYPTED PRIVATE KEY-----  MIICxjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQI2aEhi35m/scCAggA  MBQGCCqGSIb3DQMHBAihDOZw68gfKwSca*Au2E/d2a9FgHDWoinhK2nMc2MlrgL+  kpWcZ5YyUEWUw87DFKrG7dkpAYOgLIpyDatXUVFy2EekZH0Iplqo+yswtho8NtpJ  7T7KJ0nbUXo4we658Ez0EHAnWw+xZegsmJGk2+5QRCALDFyYEIMp3UvqxBjPjfDM  1rEZ0j2o9U40ouDqUVxTpq7ZwHkx/EkB8xHwKpFexz8J0s6gjPy6yLUjX2ut63LD  6X4YPBQLCJIcaLZORoAQ01cxCaM+78WTLUjdhcaFvff9f1xkiUU3XrQQTpuM/3YH  MQ6SMYDAgiOLqSCiMc0VABwf0/kdBnxu9/C/CK82ehA29cVAe8o7HgKg+WszCzTE  +QRCJ2fa7nOd7UXzCDfKh5Hhq1RjLFocVK8OW7tIgW3ircltM1ow30FfEzIdvzmv  LP0QhfGI3o9VT7r5qihGxtXtnGeUEGwvK0j0ozznfsNej7sVFP0Jfw39TdUlEENh  OPjtuBBBHv/oafQ3jqYnrI4R12ZrEU0acm85vRJm32K1RT1ROMFpc5sU20S8nMGC  I3iCzUlJPQF0t07bKexayvfWlJVAwEqBBCPTnvfTMBEt33iC72dQELbzMAM/n7th  TcY/sReO/J4beGk3//c7PImKIOcIvKF9Gp99l/+BM/LMZ7Thd/qwMOV6Eb3T4BvY  ItC+P5Lr29XeINmLRHXKwr27uTxX0fwDpmpwkPbGreVXA2cCxHnEzkh2WP3qGa7q  +Cwi03ISTEcZbNxLRGArtFUOIvNpz4+FS07OLWVKGl6K6bTffBx1tlZ492SqyNAC  7aP4/4I9Malnt0VjRKYPBCkTvVhoWBG+ThoOav5IV+w7ZDy8mtcrcAII  -----END ENCRYPTED PRIVATE KEY-----";    const PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----  MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAqjJs08oHvNdhlWC+kGBd90PD  7CVjClhRTk3nn+2NNaP4Bi5N/A18rdrV6clNAGUz4i/5q/VQXeLiGYYqgmAkKCJe  gReMsfcnoOSWu+Tvxih/48pu1hwBrmMLFZPOOUWQ9YjQEo7SYBe0HKoEl6XMqNwz  HV7sk9x6BKz9QeLi5QIDAQAB  -----END PUBLIC KEY-----";    private static $private_key;    private static $public_key;      public static function private_encrypt($str){      self::setup_key();      if(openssl_private_encrypt($str, $encrypted, self::$private_key))        return $encrypted;    }    public static function private_decrypt($str){      self::setup_key();      if(openssl_private_decrypt($str, $decrypted, self::$private_key))        return $decrypted;    }    public static function public_decrypt($str){      self::setup_key();      if(openssl_public_decrypt($str, $decrypted, self::$public_key))        return $decrypted;    }    public static function public_encrypt($str){      self::setup_key();      if(openssl_public_encrypt($str, $encrypted, self::$public_key))        return $encrypted;    }    private static function setup_key(){      if (!self::$private_key){        // 这里的test就是在生成证书的时候设置的私钥密码        self::$private_key = openssl_pkey_get_private(self::PRIVATE_KEY, "test");      }      if (!self::$public_key)        self::$public_key = openssl_pkey_get_public(self::PUBLIC_KEY);    }  }

iOS客户端的加解密

首先我们需要导入Security.framework,在ios中,我们主要关注四个函数

  • SecKeyEncrypt:使用公钥对数据进行加密
  • SecKeyDecrypt:使用私钥对数据进行解密
  • SecKeyRawVerify:使用公钥对数字签名和数据进行验证,以确认该数据的来源合法性。
  • SecKeyRawSign:使用私钥对数据进行摘要并生成数字签名

从这几个函数中,我们可以看到,我们使用公钥能做的事情就有两个:加密数据,以及对服务器端发来的数据进行签名认证,但是如果你想跟我之前想的一样,要使用公钥来对数据进行解密,那就没有自带API了。如果想在服务器端使用私钥加密数据,然后再在客户端使用公钥进行解密,以图这样来对交互数据进行加密,看来是行不通的。其实也应该是这样,公钥是公开的,因为他可以编译到二进制文本里面就认为他不能被获取其实是不对的。同时,RSA因为都是做大数的运算,算法性能上比较差,如果做大数据量的加解密,对IOS来讲,肯定也是不合适的。

这里就把使用公钥进行加密的代码贴出来:

// 我们在前面使用openssl生成的public_key.der文件的base64值,用你自己的替换掉这里  #define RSA_KEY_BASE64 @"MIIC5DCCAk2gAwIBAgIJALUk4hrYth9oMA0GCSqGSIb3DQEBBQUAMIGKMQswCQYDVQQGEwJ  DTjERMA8GA1UECAwIU2hhbmdoYWkxETAPBgNVBAcMCFNoYW5naGFpMQ4wDAYDVQQKDAVCYWl5aTEOMAwGA1UECwwFQmFpeWk  xEDAOBgNVBAMMB1lvcmsuR3UxIzAhBgkqhkiG9w0BCQEWFGd5cTUzMTk5MjBAZ21haWwuY29tMB4XDTExMTAyNjAyNDUzMlo  XDTExMTEyNTAyNDUzM1owgYoxCzAJBgNVBAYTAkNOMREwDwYDVQQIDAhTaGFuZ2hhaTERMA8GA1UEBwwIU2hhbmdoYWkxDjA  MBgNVBAoMBUJhaXlpMQ4wDAYDVQQLDAVCYWl5aTEQMA4GA1UEAwwHWW9yay5HdTEjMCEGCSqGSIb3DQEJARYUZ3lxNTMxOTk  yMEBnbWFpbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAK3cKya7oOi8jVMkRGVuNn/SiSS1y5knKLh6t98JukB  DJZqo30LVPXXL9nHcYXBTulJgzutCOGQxw8ODfAKvXYxmX7QvLwlJRFEzrqzi3eAM2FYtZZeKbgV6PximOwCG6DqaFqd8X0W  ezP1B2eWKz4kLIuSUKOmt0h3RpIPkatPBAgMBAAGjUDBOMB0GA1UdDgQWBBSIiLi2mehEgi/MwRZOld1mLlhl7TAfBgNVHSM  EGDAWgBSIiLi2mehEgi/MwRZOld1mLlhl7TAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAB0GUsssoVEDs9vQxk0  DzNr8pB0idfI+Farl46OZnW5ZwPu3dvSmhQ+yRdh7Ba54JCyvRy0JcWB+fZgO4QorNRbVVbBSuPg6wLzPuasy9TpmaaYaLLK  Iena6Z60aFWRwhazd6+hIsKTMTExaWjndblEbhAsjdpg6QMsKurs9+izr"    static SecKeyRef _public_key=nil;  + (SecKeyRef) getPublicKey{ // 从公钥证书文件中获取到公钥的SecKeyRef指针    if(_public_key == nil){      NSData *certificateData = [Base64 decode:RSA_KEY_BASE64];      SecCertificateRef myCertificate =  SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)certificateData);      SecPolicyRef myPolicy = SecPolicyCreateBasicX509();      SecTrustRef myTrust;      OSStatus status = SecTrustCreateWithCertificates(myCertificate,myPolicy,&myTrust);      SecTrustResultType trustResult;      if (status == noErr) {        status = SecTrustEvaluate(myTrust, &trustResult);      }      _public_key = SecTrustCopyPublicKey(myTrust);      CFRelease(myCertificate);      CFRelease(myPolicy);      CFRelease(myTrust);    }    return _public_key;  }    + (NSData*) rsaEncryptString:(NSString*) string{    SecKeyRef key = [self getPublicKey];    size_t cipherBufferSize = SecKeyGetBlockSize(key);    uint8_t *cipherBuffer = malloc(cipherBufferSize * sizeof(uint8_t));    NSData *stringBytes = [string dataUsingEncoding:NSUTF8StringEncoding];    size_t blockSize = cipherBufferSize - 11;    size_t blockCount = (size_t)ceil([stringBytes length] / (double)blockSize);    NSMutableData *encryptedData = [[[NSMutableData alloc] init] autorelease];    for (int i=0; i<blockCount; i++) {      int bufferSize = MIN(blockSize,[stringBytes length] - i * blockSize);      NSData *buffer = [stringBytes subdataWithRange:NSMakeRange(i * blockSize, bufferSize)];      OSStatus status = SecKeyEncrypt(key, kSecPaddingPKCS1, (const uint8_t *)[buffer bytes],                                      [buffer length], cipherBuffer, &cipherBufferSize);      if (status == noErr){        NSData *encryptedBytes = [[NSData alloc] initWithBytes:(const void *)cipherBuffer length:cipherBufferSize];        [encryptedData appendData:encryptedBytes];        [encryptedBytes release];      }else{        if (cipherBuffer) free(cipherBuffer);        return nil;      }    }    if (cipherBuffer) free(cipherBuffer);  //  NSLog(@"Encrypted text (%d bytes): %@", [encryptedData length], [encryptedData description]);  //  NSLog(@"Encrypted text base64: %@", [Base64 encode:encryptedData]);    return encryptedData;  }

转自:http://bbs.9ria.com/thread-238366-1-1.html

Similar Posts:

  • iOS下使用SHA1WithRSA算法加签源码

    首先了解一下几个相关概念,以方便后面遇到的问题的解决: RSA算法:1977年由Ron Rivest.Adi Shamirh和LenAdleman发明的,RSA就是取自他们三个人的名字.算法基于一个数论:将两个大素数相乘非常容易,但要对这个乘积的结果进行因式分解却非常困难,因此可以把乘积公开作为公钥.该算法能够抵抗目前已知的所有密码攻击.RSA算法是一种非对称算法,算法需要一对密钥,使用其中一个加密,需要使用另外一个才能解密.我们在进行RSA加密通讯时,就把公钥放在客户端,私钥留在服务器. PE

  • Java中使用OpenSSL生成的RSA公私钥进行数据加解密

    本文出处:http://blog.csdn.net/chaijunkun/article/details/7275632,转载请注明.由于本人不定期会整理相关博文,会对相应内容作出完善.因此强烈建议在原始出处查看此文. RSA是什么:RSA公钥加密算法是1977年由Ron Rivest.Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的.RSA取名来自开发他们三者的名字.RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的所有密码攻击,已被ISO推荐为公钥数据加

  • AES算法 java与C加解密兼容

    aes算法 key256位,java进行加密 环境 jdk1.7,需要UnlimitedJCEPolicyJDK7,来支持key256位,默认只支持128位 try { Cipher cp = Cipher.getInstance("AES/CBC/PKCS5Padding"); cp.init(Cipher.ENCRYPT_MODE, secretKey, dps); return cp.doFinal(hexstr2byte(str)); } catch (Exception e)

  • Silverlight4中利用System.Numerics.BigInteger实现RSA算法

    在Silverlight4 Beta版本发布的时候,Silverlight4 Beta的SDK中还不包含System.Numerics.dll库.要实现RSA算法,还得利用其他BigInteger类.可参见我上一篇文章<Silverlight中非对称加密及数字签名RSA算法的实现>. 现在Silverlight4正式发布了.在Silverlight4正式版的SDK中包含了System.Numerics.dll库.并且该库中实现了BigInteger类.因此,现在要在Silverlight下实现

  • [iOS 登陆加密] RSA加密

    java与IOS之间的RSA加解密 http://yuur369.iteye.com/blog/1769395 Java中使用OpenSSL生成的RSA公私钥进行数据加解密 http://blog.csdn.net/chaijunkun/article/details/7275632 一篇搞定RSA加密与SHA签名|与Java完全同步 http://www.jianshu.com/p/a1bad1e2be55 iPV6换SDK后上传版本报错:ERROR ITMS-90530,ERROR ITMS

  • 基于RSA算法的ios客户端加密和C#服务端解密的解决方案

    来源:http://theosoft.net/ RSA是一种比较常用的非对称加密算法,其原理是基于大整数因数分解的计算安全,这里不做介绍.非对称加密的好处在于其密码分为公钥和私钥两部分,你可以随意分发你的公钥,让用户用来加密数据:等上传到服务器端后再用私钥就可以解密里面的数据.所以,这样的体系特别适合用于客户端–尤其使手机客户端的数据加密,而不用担心你的程序被反编译.破解后泄露了你的密码. 正是因为有着这么好的安全特性,早在年初,我还在使用windows mobile手机的时候,就把RSA算法写

  • 【笔记】如何快速生成随机数 RSA算法

    今天学了一下随机化贪心,于是也就顺势学了一下随机数生成. 以下是扯淡 众所周知,系统有一个rand()函数,windows下可以生成32767以内的随机数,linux下可以生成2147483647以内的随机数.它是用线性同余的方法生成.形如: Xn=(aXn-1+b)%c 于是每次都要取一个随机数种子,作为X0来递推.一般情况都这么写: srand(time(0)); 这样以时间作为种子,每一秒的种子就不同,得到的随机数也就不同了. 然而,每一秒!!这样间隔还是太长了,还是不满足竞赛的需求. 于

  • RSA算法实现

    RSA算法基础->实践 讲讲自己学习RSA中的实践过程,已经对RSA熟悉的看家就不用在此浪费时间了. 基础 RSA算法非常简单,概述如下: 找两素数p和q 取n=p*q 取t=(p-1)*(q-1) 取任何一个数e,要求满足e 取d*e%t==1 这样最终得到三个数: n d e 设消息为数M (M 设c=(M**d)%n就得到了加密后的消息c 设m=(c**e)%n则 m == M,从而完成对c的解密. 注:**表示次方,上面两式中的d和e可以互换. 在对称加密中: n d两个数构成公钥,可以

  • RSA算法详解

    http://blog.csdn.net/starryheavens/article/details/8536238 数论,数学中的皇冠,最纯粹的数学.早在古希腊时代,人们就开始痴迷地研究数字,沉浸于这个几乎没有任何实用价值的思维游戏中.直到计算机诞生之后,几千年来的数论研究成果突然有了实际的应用,这个过程可以说是最为激动人心的数学话题之一.最近我在<程序员>杂志上连载了<跨越千年的 RSA 算法>,但受篇幅限制,只有一万字左右的内容.其实,从数论到 RSA 算法,里面的数学之美哪

  • RSA算法原理(一)转自松鼠会

    如果你问我,哪一种算法最重要?我可能会回答"公钥加密算法". 因为它是计算机通信安全的基石,保证了加密数据不会被破解.你可以想象一下,信用卡交易被破解的后果. 进入正题之前,我先简单介绍一下,什么是"公钥加密算法". 一.一点历史 1976年以前,所有的加密方法都是同一种模式: (1)甲方选择某一种加密规则,对信息进行加密: (2)乙方使用同一种规则,对信息进行解密. 由于加密和解密使用同样规则(简称"密钥"),这被称为"对称加密算法&

Tags: