RSA基本用法原理

来源:互联网 发布:照片添加文字软件 编辑:程序博客网 时间:2024/06/05 00:47

RSA简介

RSA算法是一种非对称加密算法,常被用于加密数据传输.如果配合上数字摘要算法(SHA MD5), 也可以用于文件签名. 这种加密传输方式会被用在网银类App中.虽然网银会采用全站https方案, 但是在安全登录这块会使用另一个证书对登录信息加密, 这样可以双层确保数据安全.

本文环境

  1. mac os
  2. openssl-1.0.1j, openssl需要使用1.x版本,推荐使用homebrew
  3. 安装. Java 8

RSA基本原理

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

  1. 公钥(public key): 用于加密数据. 用于公开, 一般存放在数据提供方, 例如iOS客户端.
  2. 私钥(private key):用于解密数据. 必须保密, 私钥泄露会造成安全问题.
    iOS中的Security.framework提供了对RSA算法的支持.这种方式需要对密匙对进行处理, 根据public key生成证书, 通过private key生成p12格式的密匙.
    除了Secruty.framework, 也可以将openssl库编译到iOS工程中, 这可以提供更灵活的使用方式. 本文使用Security.framework的方式处理RSA.

使用Openssl生成秘钥对

// 在bash命令下输入一下命令,需要一步一步地进行#!/usr/bin/env bashecho "Generating RSA key pair ..."  echo "1024 RSA key: private_key.pem"openssl genrsa -out private_key.pem 1024echo "create certification require file: rsaCertReq.csr"openssl req -new -key private_key.pem -out rsaCertReq.csrecho "create certification using x509: rsaCert.crt"openssl x509 -req -days 3650 -in rsaCertReq.csr -signkey private_key.pem -out rsaCert.crtecho "create public_key.der For IOS"openssl x509 -outform der -in rsaCert.crt -out public_key.derecho "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.crtecho "create rsa_public_key.pem For Java"openssl rsa -in private_key.pem -out rsa_public_key.pem -puboutecho "create pkcs8_private_key.pem For Java"openssl pkcs8 -topk8 -in private_key.pem -out pkcs8_private_key.pem -nocryptecho "finished."

Tips:

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

iOS如何使用RSA

由于iOS要依赖Base64编码库,可以采用Cocoapods或者直接fork下github上源代码直接添加到项目中。

如使用Cocoapods,在Podfile中添加一行 pod ‘Base64nl’ , ‘~> 1.2’

加密数据

RSAEncryptor *rsa = [[RSAEncryptor alloc] init];    NSLog(@"利用rsa 机密数据");    NSString *publicKeyPath = [[NSBundle mainBundle] pathForResource:@"public_key" ofType:@"der"];    NSLog(@"公钥文件路径是: %@", publicKeyPath);    [rsa loadPublicKeyFromFile:publicKeyPath];    NSString *securityText = @"hello ~";    NSString *encryptedString = [rsa rsaEncryptString:securityText];    NSLog(@"加密后的字符串数据是: %@", encryptedString);    [rsa rsaEncryptString:securityText];  执行的操作是:先对字符串加密,加密后的字符串在进行一次Base64编码。

终端输出:加密后的字符串数据是: I1Mnu33cU7QcgaC9uo2bxV0vyfJSqAwyC3DZ+p8jm0G2EmcClarrR5R2xLDdXqvtKj+UJbES7TT+AgkK1NDoQvOJBY+jkmrpAchmRbV2jvi3cEZYQG955jrdSAu21NzQe8xWtEc3YzP+TACPdP4B3Cyy0u8N2RcSFWyxu0YKPXE=

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

NSLog(@"利用rsa破译:");    [rsa loadPrivateKeyFromFile:[[NSBundle mainBundle] pathForResource:@"private_key" ofType:@"p12"] password:@"123456"];    NSString *decryptedString = [rsa rsaDecryptString:encryptedString];    NSLog(@"破译后的字符串数据是: %@", decryptedString);

终端输出:
利用rsa破译:
破译后的字符创数据是:hello~

服务器端解码数据(Java破译密码)

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

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

Java具体解码步骤:

  1. 加载pkcs8 private key:

    • 读取private key文件
    • 去掉private key头尾的”—–BEGIN PRIVATE KEY —–”和”—–BEGIN PRIVATE KEY—–”
    • 删除private key中的换行
    • 对处理后的数据进行Base64解码
    • 使用解码后的数据生成private key.
  2. 解密数据:

    • 对数据进行Base64解码
    • 使用RSA decrypt数据.

在这里就可以贴上服务器端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));    }}
0 0
原创粉丝点击