java ios 字符串_Java 与 iOS使用RSA 加密签名
RSA算法是一种非对称加密算法,常被用于加密数据传输.如果配合上数字摘要算法, 也可以用于文件签名.
本文将讨论如何在iOS中使用RSA传输加密数据.
本文环境
mac os
openssl-1.0.1j, openssl需要使用1.x版本, 推荐使用homebrew安装.
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生成密匙对
#!/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如何加载使用证书
将下面代码添加到项目中:
代码依赖 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 rsadecrypted data: hello ~
在服务器端解码数据 ** (Java) **
在Java中解码需要使用下述指令生成的pkcs8 private key:
gen shell 写道
openssl pkcs8 -topk8 -in private_key.pem -out pkcs8_private_key.pem -nocrypt
具体解码步骤:
加载pkcs8 private key:
读取private key文件
去掉private key头尾的"-----BEGIN PRIVATE KEY-----"和"-----BEGIN PRIVATE KEY-----"
删除private key中的换行
对处理后的数据进行Base64解码
使用解码后的数据生成private key.
解密数据:
对数据进行Base64解码
使用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算法实现对文件的数字签名.
java ios 字符串_Java 与 iOS使用RSA 加密签名相关推荐
- iOS 字符串截取、iOS 字符串替换、iOS 字符串分隔、iOS 字符串匹配、截取字符串、匹配字符串、分隔字符串
iOS之字符串截取.iOS 字符串替换.iOS字符串分隔.iOS之字符串匹配.截取字符串.匹配字符串.分隔字符串 1.iOS 字符串截取 //1.ios截取字符串NSString *string =@ ...
- java 格式化字符串_Java入门 - 语言基础 - 14.String类
1.概述 字符串广泛应用 在 Java 编程中,在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串. 2.创建字符串 创建字符串最简单的方式如下: String gr ...
- java join字符串_Java字符串join()
java join字符串 Java String join() function is used to join multiple strings to create a new string wit ...
- java equals 字符串_Java String 字符串 比较 == equals
1.==该运算符表示指向字符串的引用是否相同,如t1==t2这种情况, 是因为在java中字符串的值是不可改变的,相同的字符串在内存中只会存一份, 所以t1和t2指向的是同一个对象,而t1==t4返回 ...
- java 去重字符串_Java之字符串去重的简述
在编写JS代码时,我们发现可以通过JSON的特性消除重复数据,并快速的消除数据,下文是Java之字符串去重的简述?让爱站技术频道小编带你一起进入下文了解一下吧! 字符串在任何应用中都占用了大量的内存. ...
- java split函数的用法,java拆分字符串_java中split拆分字符串函数用法
摘要 腾兴网为您分享:java中split拆分字符串函数用法,中信期货,掌上电力,星球联盟,淘集集等软件知识,以及韩剧精灵,每日英语听力vip,龙卷风收音机,优衣库,中国平煤神马集团协同办公系统,光晕 ...
- 学习笔记——RSA加密签名
前后端请求,内容涉及用户信息时一般会要求对数据进行加密:对于支付系统的接口,为了保证参数不被篡改(如订单金额.支付单号等),需要对下单参数进行签名: 本篇介绍RSA相关的知识以及应用场景,包括:对称加 ...
- java清空字符串_java面向对象,垃圾回收机制
一.类的属性 属性用于定义该类或该类对象包含的数据或者说静态特征.属性作用范围是整个类体. 在定义成员变量时可以对其初始化,如果不对其初始化,Java使用默认的值对其初始化. 二.UML图 三.类和对 ...
- java连接字符串_Java字符串连接运算符
Java字符串连接运算符 在java语言中所有的字符串都使用半角双引号括起来的,字符串属于引用数据类型,不属于基本数据类型的范畴,怎么定义一个字符串的变量呢?例如:String name = &quo ...
最新文章
- 数据中心怎么关机?光有UPS还不够
- 【科普】boy and girl,你是不是对算法工程师有误解
- vue js前端根据所需参数生成二维码并下载
- Python—实训day8—掌握DataFrame的常用操作
- LeetCode 1885. Count Pairs in Two Arrays(二分查找)
- linux搭建web服务器原理,【LINUX】linux搭建web服务器
- 小程序中view的自定义属性获取
- C语言-数据结构-可变长顺序表的删除操作
- 模糊控制器设计基本方法
- 元胞自动机(又称细胞自动机)
- 通信原理学习笔记5-1:数字调制——脉冲成形滤波器选择(码间串扰、Nyquist准则、升余弦滚降滤波器、眼图)
- Numpy中的向量运算
- 各社交网站页面分享代码链接
- 2021 春季新品发布会上,苹果推出了全新配件 AirTag
- 3.3 WSN路由协议
- 电脑网线,电脑网线插了没反应怎么回事?如何解决?
- 2021届 联发科技视频二面 嵌入式软件
- oracle数据库系统学习,Oracle数据库学习第二天
- 目前全球和中国的区块链专利申请状况和布局状况如何?
- Windows系统ping不通同网段主机解决方法
热门文章
- android权威指南十三章,《Android编程权威指南》第30~32以及第34章读书笔记
- Intel Haswell/Broadwell架构/微架构/流水线 (3)-流水线乱序引擎
- Pentium 4处理器架构/微架构/流水线(1) - 概述
- python中xlrd.open_workbook_python解决open()函数、xlrd.open_workbook()函数文件名包含中文,sheet名包含中文报错的问题...
- mysql++3307,mysql多实例配置方法
- java ora 01002_遇到了ora-01002,fetch out of sequence
- python pandas 排序_python – pandas:单独对每列进行排序
- python中urlLib的使用
- python在电脑哪可以找到_哪里可以找到比较靠谱的Python教程?
- UnrealEngine4-Roadmap