ios下使用rsa算法与php进行加解密通讯

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

  • 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命令行生成密钥对


1

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公钥文件:


1

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

上面这个命令就会根据输入的私钥文件生成pem格式的公钥文件了。从这里也可以看到,根据私钥,我们是可以生成相对应的公钥的,这也就是为什么我们要把公钥放在客户端,而不是私钥放在客户端的原因了。

服务器端PHP的加解密函数

闲话不多说,贴一段代码,肯定能看懂的了


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

class RSAEncryptTest {

  const PRIVATE_KEY = "-----BEGIN ENCRYPTED PRIVATE KEY-----

MIICxjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQI2aEhi35m/scCAggA

MBQGCCqGSIb3DQMHBAihDOZw68gfKwSCAoAu2E/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来讲,肯定也是不合适的。

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


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

// 我们在前面使用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;

}

时间: 2024-07-31 01:45:33

ios下使用rsa算法与php进行加解密通讯的相关文章

ios下使用RSA算法加密与java后台解密配合demo

首先了解一下几个相关概念,以方便后面遇到的问题的解决: 原网址:http://blog.csdn.net/jinglijun/article/details/7770315RSA算法:1977年由Ron Rivest.Adi Shamirh和LenAdleman发明的,RSA就是取自他们三个人的名字.算法基于一个数论:将两个大素数相乘非常容易,但要对这个乘积的结果进行因式分解却非常困难,因此可以把乘积公开作为公钥.该算法能够抵抗目前已知的所有密码攻击.RSA算法是一种非对称算法,算法需要一对密钥

iOS下使用SHA1WithRSA算法加签源码

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

[掌眼]iOS / Android / java / node.js 通用的 AES256 加解密算法

example.m NSString *text = @"text"; NSString *key32 = @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; NSData *data = [text dataUsingEncoding:NSUTF8StringEncoding]; NSString *encryptedData = [[data AES256EncryptWithKey:key32] base64EncodedStringWi

Android jni aes加解密,实现文件的加解密,具体实现可以自行修改,上面的代码为简单介绍,下面的是JNI端实现文件加解密,可以修改为字符串加解密

#include "aes.h" #include "modes.h" #include "e_os2.h" #include "aes_locl.h" #include "opensslconf.h" AES_KEY aes; //aes cbc模式加解密用到的向量 unsigned char iv[AES_BLOCK_SIZE]; for (i = 0; i < AES_BLOCK_SIZE; i

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

RSA是什么:RSA公钥加密算法是1977年由Ron Rivest.Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的.RSA取名来自开发他们三者的名字.RSA是目前最有影响力的公钥加密算法,它能够 抵抗到目前为止已知的所有密码攻击,已被ISO推荐为公钥数据加密标准.目前该加密方式广泛用于网上银行.数字签名等场合.RSA算法基于一个十分简单的 数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥. OpenSSL是什

自己实现简单的RSA秘钥生成与加解密(Java )

最近在学习PKI,顺便接触了一些加密算法.对RSA着重研究了一下,自己也写了一个简单的实现RSA算法的Demo,包括公.私钥生成,加解密的实现.虽然比较简单,但是也大概囊括了RSA加解密的核心思想与流程.这里写下来与大家分享一下. RSA概述: RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准. RSA的数学基础是大整数因子分解问题,其说明如下: 给定两个素数p.q,计算乘积pq=n很容易 给定整数n,求n的素因数p.q使得n=p

加解密算法二:非对称加解密

加密和解密使用不同的密钥的一类加密算法.这类加密算法通常有两个密钥A和B,使用密钥A加密数据得到的密文,只有密钥B可以进行解密操作(即使密钥A也无法解密):相反,使用密钥B加密数据得到的密文,只有密钥A可以解密.这两个密钥分别称为私钥和公钥.私钥就是你个人保留,不能公开的密钥,而公钥则是公开给加解密操作的另一方的.根据不同用途,对数据进行加密所使用的密钥也不相同(有时用公钥加密,私钥解密:有时相反用私钥加密,公钥解密).非对称加密的代表算法是RSA算法.   RSA算法是第一个既能用于数据加密也

ios下划线变量:为什么变量前要加下划线才有用?

先看一段代码. 复制代码 appdelegate.h @property (weak) IBOutlet NSMatrix *StockType; @property (weak) IBOutlet NSMatrix *market; appdelegate.m NSCell *st=[market selectedCell]; 编译时,总是提示,找不到market变量,但是StockType却没问题. 如果根据系统建议,在market前加上下划线,变成_market却可以正常编译和执行.  但

Java 进行 RSA 加解密的例子

加密是保证数据安全的手段之一.加密是将纯文本数据转换为难以理解的密文:解密是将密文转换回纯文本.数据的加解密属于密码学的范畴.通常,加密和解密都需要使用一些秘密信息,这些秘密信息叫做密钥,将纯文本转为密文或者转回的时候都要用到这些密钥.对称加密指的是发送者和接收者共用同一个密钥的加解密方法.非对称加密(又称公钥加密)指的是需要一个私有密钥一个公开密钥,两个不同的密钥的加解密体系.尽管不同,这个密钥对的这两个部分在算法上是有关联的.一个密钥将纯文本加密,另一个将密文解密.没有一个密钥能够把加密和加