`
witcheryne
  • 浏览: 1099505 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

iOS中使用RSA对数据进行加密解密

阅读更多

 

RSA算法是一种非对称加密算法,常被用于加密数据传输.如果配合上数字摘要算法, 也可以用于文件签名.

本文将讨论如何在iOS中使用RSA传输加密数据.

本文环境

  • mac os 
  • openssl-1.0.1j, openssl需要使用1.x版本, 推荐使用[homebrew](http://brew.sh/)安装.
  • Java 8

RSA基本原理

RSA使用"秘匙对"对数据进行加密解密.在加密解密数据前,需要先生成公钥(public key)和私钥(private key).

  • 公钥(public key): 用于加密数据. 用于公开, 一般存放在数据提供方, 例如iOS客户端.
  • 私钥(private key): 用于解密数据. 必须保密, 私钥泄露会造成安全问题.

iOS中的Security.framework提供了对RSA算法的支持.这种方式需要对密匙对进行处理, 根据public key生成证书, 通过private key生成p12格式的密匙.

除了Secruty.framework, 也可以将openssl库编译到iOS工程中, 这可以提供更灵活的使用方式.

本文使用Security.framework的方式处理RSA.

 

使用openssl生成密匙对

Github Gist: https://gist.github.com/lvjian700/635368d6f1e421447680

 

 

#!/usr/bin/env bash
echo "Generating RSA key pair ..."
echo "1024 RSA key: private_key.pem"
openssl genrsa -out private_key.pem 1024

echo "create certification require file: rsaCertReq.csr"
openssl req -new -key private_key.pem -out rsaCertReq.csr

echo "create certification using x509: rsaCert.crt"
openssl x509 -req -days 3650 -in rsaCertReq.csr -signkey private_key.pem -out rsaCert.crt

echo "create public_key.der For IOS"
openssl x509 -outform der -in rsaCert.crt -out public_key.der

echo "create private_key.p12 For IOS. Please remember your password. The password will be used in iOS."
openssl pkcs12 -export -out private_key.p12 -inkey private_key.pem -in rsaCert.crt

echo "create rsa_public_key.pem For Java"
openssl rsa -in private_key.pem -out rsa_public_key.pem -pubout
echo "create pkcs8_private_key.pem For Java"
openssl pkcs8 -topk8 -in private_key.pem -out pkcs8_private_key.pem -nocrypt

echo "finished."

 

 

 

Tips:

  • 在创建证书的时候, terminal会提示输入证书信息. 根据wizard输入对应信息就OK. 
  • 在创建p12密匙时, 会提示输入密码, 此时的密码必须记住, 之后会用到.
  • 如果上面指令有问题,请参考最新的openssl官方文档, 以官方的为准. 之前在网上搜索指令, 被坑了一圈之后, 还是会到啃官方文档上. 每条指令文档在最后都会有几个sample,参考sample即可.

iOS如何加载使用证书

将下面代码添加到项目中:

https://gist.github.com/lvjian700/204c23226fdffd6a505d

 

代码依赖Base64编码库, 如果使用cocoapods, 可以讲下面依赖添加到Podfile:

 

pod 'Base64nl', '~> 1.2'

 

 

加密数据

 

RSAEncryptor *rsa = [[RSAEncryptor alloc] init];

    NSLog(@"encryptor using rsa");
    NSString *publicKeyPath = [[NSBundle mainBundle] pathForResource:@"public_key" ofType:@"der"];
    NSLog(@"public key: %@", publicKeyPath);
    [rsa loadPublicKeyFromFile:publicKeyPath];

    NSString *securityText = @"hello ~";
    NSString *encryptedString = [rsa rsaEncryptString:securityText];
    NSLog(@"encrypted data: %@", encryptedString);

 

 

__[rsa rsaEncryptString:securityText]__会返回decrypted base64编码的字符串:

console out 写道
encrypted data: I1Mnu33cU7QcgaC9uo2bxV0vyfJSqAwyC3DZ+p8jm0G2EmcClarrR5R2xLDdXqvtKj+UJbES7TT+AgkK1NDoQvOJBY+jkmrpAchmRbV2jvi3cEZYQG955jrdSAu21NzQe8xWtEc3YzP+TACPdP4B3Cyy0u8N2RcSFWyxu0YKPXE=

 

解密数据

在iOS下解码需要先加载private key, 之后在对数据解码. 解码的时候先进行Base64 decode, 之后在用private key decrypt加密数据.

 

 

NSLog(@"decryptor using rsa");
    [rsa loadPrivateKeyFromFile:[[NSBundle mainBundle] pathForResource:@"private_key" ofType:@"p12"] password:@"123456"];
    NSString *decryptedString = [rsa rsaDecryptString:encryptedString];
    NSLog(@"decrypted data: %@", decryptedString);

 

 

之后会输出解密后的数据:

console 写道
decryptor using rsa
decrypted data: hello ~

 

在服务器端解码数据(Java)

 

在Java中解码需要使用下述指令生成的pkcs8 private key:

 

gen shell 写道
openssl pkcs8 -topk8 -in private_key.pem -out pkcs8_private_key.pem -nocrypt

 

具体解码步骤:

 

  1. 加载pkcs8 private key:
    1. 读取private key文件
    2. 去掉private key头尾的"-----BEGIN PRIVATE KEY-----"和"-----BEGIN PRIVATE KEY-----"
    3. 删除private key中的换行
    4. 对处理后的数据进行Base64解码
    5. 使用解码后的数据生成private key.
  2. 解密数据:
    1. 对数据进行Base64解码
    2. 使用RSA decrypt数据.

这里我将iOS中"hello ~"加密的数据在Java中进行解码:

 

 

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;

import static java.lang.String.format;

public class Encryptor {

    public static void main(String[] args) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        PrivateKey privateKey = readPrivateKey();

        String message = "AFppaFPTbmboMZD55cjCfrVaWUW7+hZkaq16Od+6fP0lwz/yC+Rshb/8cf5BpBlUao2EunchnzeKxzpiPqtCcCITKvk6HcFKZS0sN9wOhlQFYT+I4f/CZITwBVAJaldZ7mkyOiuvM+raXMwrS+7MLKgYXkd5cFPxEsTxpMSa5Nk=";
        System.out.println(format("- decrypt rsa encrypted base64 message: %s", message));
        // hello ~,  encrypted and encoded with Base64:
        byte[] data = encryptedData(message);
        String text = decrypt(privateKey, data);
        System.out.println(text);
    }

    private static String decrypt(PrivateKey privateKey, byte[] data) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decryptedData = cipher.doFinal(data);

        return new String(decryptedData);
    }

    private static byte[] encryptedData(String base64Text) {
        return Base64.getDecoder().decode(base64Text.getBytes(Charset.forName("UTF-8")));
    }

    private static PrivateKey readPrivateKey() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        byte[] privateKeyData = Files.readAllBytes(
                Paths.get("/Users/twer/macspace/ios_workshop/Security/SecurityLogin/tools/pkcs8_private_key.pem"));

        byte[] decodedKeyData = Base64.getDecoder()
                .decode(new String(privateKeyData)
                        .replaceAll("-----\\w+ PRIVATE KEY-----", "")
                        .replace("\n", "")
                        .getBytes());

        return KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decodedKeyData));
    }
}

 

 

 

直行成功后控制台会输出"hello ~".

 

总结

 

这种加密传输方式会被用在网银类App中.虽然网银会采用全站https方案, 但是在安全登录这块会使用另一个证书对登录信息加密, 这样可以双层确保数据安全.

基于RSA加密解密算法, 还可以将其运用在数字签名场景.以后有空在聊如何使用RSA算法实现对文件的数字签名.

 

参考资料

 

2
0
分享到:
评论
8 楼 rchongg 2016-01-09  
大神 想问的是 在一般的 登录 和 数据  加密这么两个方面(客户端+服务器端),是如何实现的吗 ? 是不是都是使用SSL 和 数字 签名加密的啊,求回复。 如不是,有其他策略吗?
7 楼 witcheryne 2015-11-29  
dgwutao 写道
我的rsa public_key和priveate_key不是自己生成的,是服务器生成的字符串格式,能不能用你这个代码?

可以...  RSA key本质上就是两个文本文件。 有头和尾,内容是编码过的密匙文本。

6 楼 dgwutao 2015-11-27  
我的rsa public_key和priveate_key不是自己生成的,是服务器生成的字符串格式,能不能用你这个代码?
5 楼 Vanessa_Rain 2015-11-08  
亲,可不可以把你的把你的两个文件借我用一下。我这边不能用呀。可以发249058630@qq.com邮箱里。
4 楼 ab0809 2015-01-08  
还有哈,就是您在验签的方法中有个kSecPaddingPKCS1SHA1,这个是指什么呢?

/* For SecKeyRawSign/SecKeyRawVerify only, data to be signed is a SHA1
       hash; standard ASN.1 padding will be done, as well as PKCS1 padding
       of the underlying RSA operation. */
    kSecPaddingPKCS1SHA1 = 0x8002,

我看Security.framework中是这么写的。想问一下,这个是和签名以及验签有关是吗,那我如果是要验签支付宝的数据的话,是不是要根据支付宝的签名的方式来选择这个参数呢。
不好意思麻烦了~
3 楼 ab0809 2015-01-08  
我说的“权威”是指比较多人用的哈。哈哈忽略我这个菜鸟 我现在因为要接支付宝,所以要用到RSA的。它的demo是把openssl的库引入,然后直接调用c函数,但是不知道他们是哪里抄来的。RSA只封装了签名和验证签名。没有加密和解密的方法。我要用解密的,所以就找到您的文章。想请教一下,
(1)为什么每次加密得到的字符串都不一样
(2)方法中有一些malloc的调用,好像没有看到free的地方,会不会对内存有影响
(3)之后会不会添加签名的方法
(4)我是打算在iOS客户端进行RSA的解密和验签,签名等,这样的话我的私钥应该怎么保存比较好呢,我看您好像是用p12文件是吗。
2 楼 witcheryne 2015-01-08  
ab0809 写道
感觉RSA的用法挺清晰简单的,不知道您在具体使用中有什么问题吗?因为objective-C的RSA好像没有什么比较权威的库。

iOS Security.framework 已经有很好的支持.
MD5/AES 等加密算法也有基本支持...

其他的有openssl. 

不知道你说的权威是只什么?   
一般C或者C++库都可以编译到iOS中使用.  Openssl 应该是最权威的.
1 楼 ab0809 2015-01-08  
感觉RSA的用法挺清晰简单的,不知道您在具体使用中有什么问题吗?因为objective-C的RSA好像没有什么比较权威的库。

相关推荐

    IOS RSA加密 分段解密

    2. **iOS中的加密库**:在iOS中,我们可以使用内置的安全框架`Security`来实现RSA加密。这个框架提供了`SecKey`类,可以用于处理公钥和私钥,以及`SecRandomCopyBytes`函数生成随机数。 3. **数据分段**:由于RSA的...

    ios-iOS RSA加密与解密.zip

    iOS RSA加密与解密Demo:https://github.com/fuaiyi/RSAEncryption博客:http://www.jianshu.com/u/b1d7ade703b4

    Object-C-在iOS上使用Object-C进行RSA算法的加密+解密实现.zip

    总之,使用Object-C在iOS上实现RSA加密解密涉及理解算法原理、导入导出密钥、调用Security框架的API以及处理可能出现的问题。通过掌握这些知识,开发者可以创建安全的应用程序,保护用户数据的安全。

    在iOS上使用Object-C进行RSA算法的加密+解密实现代码.zip

    在iOS平台上使用Objective-C进行RSA加密和解密通常涉及几个步骤,包括生成RSA密钥对、使用公钥加密数据、以及使用私钥解密数据。以下是一个简化的步骤说明和示例代码,展示了如何使用Objective-C和CommonCrypto库...

    swift-RSA加密解密

    在描述的场景中,公钥通常在客户端使用,对数据进行加密,然后发送给服务器,服务器持有私钥,用以解密接收到的数据,确保了信息的安全性。 在Swift开发中,处理RSA加密解密通常会涉及以下几个关键知识点: 1. **...

    RSA加密解密的使用,含jsencrypt.js文件(uni-app也可用)

    RSA加密解密是一种广泛应用于网络安全中的非对称加密算法,由Ron Rivest、Adi Shamir和Leonard Adleman三位科学家在1977年提出,因此得名RSA。这种算法基于大数因子分解的困难性,为数据提供了一种安全的传输方式。 ...

    iOS加密解密之rsa完整代码

    4. **代码实现**:在描述中提到的“IOS-RSA”压缩包中,应该包含了完整的Objective-C或Swift代码示例,用于演示如何在实际项目中使用RSA加密解密。这些代码可能包括密钥生成、公钥加密和私钥解密的关键函数,以及...

    iOS之RSA加密解密(亲测可用)

    在iOS开发中,数据安全是至关重要的...在iOS项目中实现RSA加密解密不仅能够保护用户的隐私,还可以符合App Store的安全规定,确保应用的合规性。通过理解并正确实施RSA加密,开发者可以构建更加安全、可靠的应用程序。

    iOS中使用RSA加密详解

    生成的public_key.der和private_key.p12文件是iOS应用中进行RSA加密解密的关键。导入到iOS工程中的步骤如下: 1. 新建工程,并添加Security.framework框架,因为iOS加密操作依赖于这个框架提供的API。 2. 将DER格式...

    iOS之RSA加密并实现解密

    本主题将详细介绍如何在iOS中使用RSA加密并实现解密,以及涉及到的相关知识点。 首先,我们需要了解RSA的工作原理。RSA(Rivest-Shamir-Adleman)是一种基于大数因子分解困难性的公钥加密算法。它包含一对密钥:...

    RSA加密解密Demo

    这个Demo可能还包含了如何在iOS项目中集成RSA加密解密的步骤,以及如何将加密解密逻辑与应用程序的其他部分(如网络请求、本地存储)结合的示例。通过阅读和理解这个Demo,开发者可以更好地理解和应用RSA加密技术,...

    Object-C-在iOS上使用Object-C进行RSA算法的加密+解密实现源代码

    本教程将详细讲解如何在iOS项目中使用Object-C实现RSA算法的加密和解密功能。 了解RSA的基本原理至关重要。RSA是一种公钥密码体制,基于两个大素数的乘积难以因式分解这一事实。它包含一对密钥:公钥和私钥。公钥...

    iOS RSA 加密解密

    在iOS中实现RSA加密解密,通常需要以下步骤: 1. **生成密钥对**:使用苹果的CryptoKit框架或者OpenSSL库,开发者可以生成RSA密钥对。密钥对通常包含一个公钥和一个私钥,公钥可以在客户端和服务端之间安全交换,而...

    ios RSA加密 苹果官方demo

    在iOS开发中,RSA是一种...通过研究苹果官方的CryptoExercise示例,开发者可以深入理解如何在iOS应用中实施RSA加密,确保数据的安全性。这不仅有助于提高应用的安全性,也为遵循苹果的App Store审核指南提供了基础。

    iOS RSA 加密和Base64

    在iOS中使用RSA加密,通常会经历以下几个步骤: 1. 生成RSA密钥对:使用`SecKeyGeneratePair`函数,指定键的大小(通常是2048位或更长),生成公钥和私钥。 2. 导出公钥和私钥:公钥可以导出为PEM格式,以便在服务器...

    IOS开发rsa加密,解密,公钥,私钥导入

    本文将深入探讨如何在iOS应用中实现RSA加密和解密,以及如何导入公钥和私钥。 首先,理解RSA的核心原理至关重要。RSA(Rivest–Shamir–Adleman)是一种非对称加密算法,它使用一对密钥:公钥和私钥。公钥用于加密...

    iOS--RSA加密文件(带证书)

    本文将深入探讨如何在iOS中使用RSA加密技术,并结合证书进行文件加密。我们将关注以下关键知识点: 1. RSA算法原理: RSA(Rivest-Shamir-Adleman)是一种公钥加密技术,基于大整数因子分解的困难性。它由一对密钥...

    android和 ios 与java web服务器端的rsa 加密解密

    - **Android端**:Android应用在发送敏感数据前,使用服务器提供的公钥对数据进行加密。由于Android系统的特性,可能需要处理特定的字节顺序问题(如Big-Endian和Little-Endian),以确保数据在加密和解密过程中...

Global site tag (gtag.js) - Google Analytics