基础知识

  1. 什么是RSA?
    答:RSA是一种非对称加密算法,常用来对传输数据进行加密,配合上数字摘要算法,也可以进行文字签名。

  2. RSA加密中padding?
    答:padding即填充方式,由于RSA加密算法中要加密的明文是要比模数小的,padding就是通过一些填充方式来限制明文的长度。后面会详细介绍padding的几种模式以及分段加密。

  3. 加密和加签有什么区别?
    答:加密:公钥放在客户端,并使用公钥对数据进行加密,服务端拿到数据后用私钥进行解密;
    加签:私钥放在客户端,并使用私钥对数据进行加签,服务端拿到数据后用公钥进行验签。
    前者完全为了加密;后者主要是为了防恶意攻击,防止别人模拟我们的客户端对我们的服务器进行攻击,导致服务器瘫痪。

基本原理

RSA使用“密钥对”对数据进行加密解密,在加密解密前需要先生存公钥(Public Key)和私钥(Private Key)。
公钥(Public key): 用于加密数据. 用于公开, 一般存放在数据提供方, 例如iOS客户端。
私钥(Private key): 用于解密数据. 必须保密, 私钥泄露会造成安全问题。
iOS中的Security.framework提供了对RSA算法的支持,这种方式需要对密匙对进行处理, 根据public key生成证书, 通过private key生成p12格式的密匙。想想jave直接用字符串进行加密解密简单多了。(⊙o⊙)…

实战

证书生成

RSA加密这块公钥、私钥必不可少的。Apple是不支持直接使用字符串进行加密解密的,推荐使用p12文件。这边教大家去生成在加密中使用到的所有文件,并提供给Java使用,想当年这个公钥私钥搞了半天了。 %>_<%

  • 生成模长为1024bit的私钥
    openssl genrsa -out private_key.pem 1024
  • 生成certification require file
    openssl req -new -key private_key.pem -out rsaCertReq.csr
  • 生成certification 并指定过期时间
    openssl x509 -req -days3650-in rsaCertReq.csr -signkey private_key.pem -out rsaCert.crt
  • 生成公钥供iOS使用
    openssl x509 -outform der -in rsaCert.crt -out public_key.der
  • 生成私钥供iOS使用 这边会让你输入密码,后期用到在生成secKeyRef的时候会用到这个密码
    openssl pkcs12 -export -out private_key.p12 -inkey private_key.pem -in rsaCert.crt
  • 生成pem结尾的公钥供Java使用
    openssl rsa -in private_key.pem -out rsa_public_key.pem -pubout
  • 生成pem结尾的私钥供Java使用openssl pkcs8 -topk8 -in private_key.pem -out pkcs8_private_key.pem -nocrypt

以上所有的步骤都是在终端下完成的哦 (^__^)

生成公钥和私钥的secKeyRef

//根据你的p12文件生成私钥对应的SecKeyRef 这边返回若是nil 请检查你p12文件的生成步骤
- (SecKeyRef)getPrivateKeyRefrenceFromData:(NSData*)p12Data password:(NSString*)password { SecKeyRef privateKeyRef = NULL;
NSMutableDictionary * options = [[NSMutableDictionary alloc] init];
[options setObject: password forKey:(__bridge id)kSecImportExportPassphrase];
CFArrayRef items = CFArrayCreate(NULL, , , NULL);
OSStatus securityError = SecPKCS12Import((__bridge CFDataRef) p12Data, (__bridge CFDictionaryRef)options, &items);
if (securityError == noErr && CFArrayGetCount(items) > ) {
CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, );
SecIdentityRef identityApp = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
securityError = SecIdentityCopyPrivateKey(identityApp, &privateKeyRef);
if (securityError != noErr) {
privateKeyRef = NULL;
}
}
CFRelease(items); return privateKeyRef;
}

-

 //根据你的der文件公钥对应的SecKeyRef
- (SecKeyRef)getPublicKeyRefrenceFromeData: (NSData*)derData { SecCertificateRef myCertificate = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)derData);
SecPolicyRef myPolicy = SecPolicyCreateBasicX509();
SecTrustRef myTrust;
OSStatus status = SecTrustCreateWithCertificates(myCertificate,myPolicy,&myTrust);
SecTrustResultType trustResult;
if (status == noErr) {
status = SecTrustEvaluate(myTrust, &trustResult);
}
SecKeyRef securityKey = SecTrustCopyPublicKey(myTrust);
CFRelease(myCertificate);
CFRelease(myPolicy);
CFRelease(myTrust); return securityKey;
}

加密与解密

- (NSData*)rsaEncryptData:(NSData*)data {
SecKeyRef key = [self getPublicKey];
size_t cipherBufferSize = SecKeyGetBlockSize(key);
uint8_t *cipherBuffer = malloc(cipherBufferSize * sizeof(uint8_t));
size_t blockSize = cipherBufferSize - ;
size_t blockCount = (size_t)ceil([data length] / (double)blockSize);
NSMutableData *encryptedData = [[NSMutableData alloc] init];
for (int i=; i<blockCount; i++) {
unsigned long bufferSize = MIN(blockSize , [data length] - i * blockSize);
NSData *buffer = [data subdataWithRange:NSMakeRange(i * blockSize, bufferSize)];
OSStatus status = SecKeyEncrypt(key, kSecPaddingPKCS1, (const uint8_t *)[buffer bytes], [buffer length], cipherBuffer, &cipherBufferSize); if (status != noErr) {
return nil;
} NSData *encryptedBytes = [[NSData alloc] initWithBytes:(const void *)cipherBuffer length:cipherBufferSize];
[encryptedData appendData:encryptedBytes];
} if (cipherBuffer){
free(cipherBuffer);
} return encryptedData;
}

-

- (NSData*)rsaDecryptData:(NSData*)data {
SecKeyRef key = [self getPrivatKey]; size_t cipherBufferSize = SecKeyGetBlockSize(key);
size_t blockSize = cipherBufferSize;
size_t blockCount = (size_t)ceil([data length] / (double)blockSize); NSMutableData *decryptedData = [[NSMutableData alloc] init]; for (int i = ; i < blockCount; i++) {
unsigned long bufferSize = MIN(blockSize , [data length] - i * blockSize);
NSData *buffer = [data subdataWithRange:NSMakeRange(i * blockSize, bufferSize)]; size_t cipherLen = [buffer length];
void *cipher = malloc(cipherLen);
[buffer getBytes:cipher length:cipherLen];
size_t plainLen = SecKeyGetBlockSize(key);
void *plain = malloc(plainLen); OSStatus status = SecKeyDecrypt(key, kSecPaddingPKCS1, cipher, cipherLen, plain, &plainLen); if (status != noErr) {
return nil;
} NSData *decryptedBytes = [[NSData alloc] initWithBytes:(const void *)plain length:plainLen];
[decryptedData appendData:decryptedBytes];
} return decryptedData;
}
RSA加密中的Padding
  • RSA_PKCS1_PADDING 填充模式,最常用的模式
    要求: 输入:必须 比 RSA 钥模长(modulus) 短至少11个字节, 也就是 RSA_size(rsa) – 11 如果输入的明文过长,必须切割,然后填充。
    输出:和modulus一样长
    根据这个要求,对于1024bit的密钥,block length = 1024/8 – 11 = 117 字节

  • RSA_PKCS1_OAEP_PADDING
    输入:RSA_size(rsa) – 41
    输出:和modulus一样长

  • RSA_NO_PADDING  不填充
    输入:可以和RSA钥模长一样长,如果输入的明文过长,必须切割, 然后填充
    输出:和modulus一样长

签名与验证

//对数据进行sha256签名
- (NSData *)rsaSHA256SignData:(NSData *)plainData {
SecKeyRef key = [self getPrivatKey]; size_t signedHashBytesSize = SecKeyGetBlockSize(key);
uint8_t* signedHashBytes = malloc(signedHashBytesSize);
memset(signedHashBytes, 0x0, signedHashBytesSize); size_t hashBytesSize = CC_SHA256_DIGEST_LENGTH;
uint8_t* hashBytes = malloc(hashBytesSize);
if (!CC_SHA256([plainData bytes], (CC_LONG)[plainData length], hashBytes)) {
return nil;
} SecKeyRawSign(key,
kSecPaddingPKCS1SHA256,
hashBytes,
hashBytesSize,
signedHashBytes,
&signedHashBytesSize); NSData* signedHash = [NSData dataWithBytes:signedHashBytes
length:(NSUInteger)signedHashBytesSize]; if (hashBytes)
free(hashBytes);
if (signedHashBytes)
free(signedHashBytes); return signedHash;
}

-

 //这边对签名的数据进行验证 验签成功,则返回YES
- (BOOL)rsaSHA256VerifyData:(NSData *)plainData withSignature:(NSData *)signature {
SecKeyRef key = [self getPublicKey]; size_t signedHashBytesSize = SecKeyGetBlockSize(key);
const void* signedHashBytes = [signature bytes]; size_t hashBytesSize = CC_SHA256_DIGEST_LENGTH;
uint8_t* hashBytes = malloc(hashBytesSize);
if (!CC_SHA256([plainData bytes], (CC_LONG)[plainData length], hashBytes)) {
return NO;
} OSStatus status = SecKeyRawVerify(key,
kSecPaddingPKCS1SHA256,
hashBytes,
hashBytesSize,
signedHashBytes,
signedHashBytesSize); return status == errSecSuccess;
}

文章到此就结束了,希望这篇文章对大家有所帮助。想看demo的请点击:XYRSACryptor

相关链接:

一篇搞定RSA加密与SHA签名|与Java完全同步的更多相关文章

  1. Java三行代码搞定MD5加密

    Java三行代码搞定MD5加密 https://www.dexcoder.com/selfly/article/4026 public class MD5Test { public static vo ...

  2. 2021升级版微服务教程6—Ribbon使用+原理+整合Nacos权重+实战优化 一篇搞定

    2021升级版SpringCloud教程从入门到实战精通「H版&alibaba&链路追踪&日志&事务&锁」 教程全目录「含视频」:https://gitee.c ...

  3. 【转】C#中RSA加密解密和签名与验证的实现

    [转]C#中RSA加密解密和签名与验证的实现 RSA加密算法是一种非对称加密算法.在公钥加密标准和电子商业中RSA被广泛使用.RSA是1977年由罗纳德•李维斯特(Ron Rivest).阿迪•萨莫尔 ...

  4. Java使用RSA加密解密及签名校验

    该工具类中用到了BASE64,需要借助第三方类库:javabase64-1.3.1.jar注意:RSA加密明文最大长度117字节,解密要求密文最大长度为128字节,所以在加密和解密的过程中需要分块进行 ...

  5. C#中RSA加密解密和签名与验证的实现

    RSA加密算法是一种非对称加密算法.在公钥加密标准和电子商业中RSA被广泛使用.RSA是1977年由罗纳德•李维斯特(Ron Rivest).阿迪•萨莫尔(Adi Shamir)和伦纳德•阿德曼(Le ...

  6. 一篇搞定微信分享和line分享

    前言 在h5的页面开发中,分享是不可或缺的一部分,对于一些传播性比较强的页面,活动页之类的,分享功能极为重要.例如,京东等电商年末时会有一系列的总结h5在微信中传播,就不得不提到微信的分享机制. 微信 ...

  7. Java三行代码搞定MD5加密,测试5c短信网关的demo

    看到之前项目中,关于MD5加密的足足写了一个辅助类. 其实在Java中大部分都帮你实现好了,完成MD5加密,主要就三行代码: /** * 对字符串md5加密 * * @param str * @ret ...

  8. 阿里巴巴(alibaba)系列_druid 数据库连接池_监控(一篇搞定)记录执行慢的sql语句

    参考帖子:http://www.cnblogs.com/han-1034683568/p/6730869.html Druid数据连接池简介 Druid是Java语言中最好的数据库连接池.Druid能 ...

  9. 一篇搞定MongoDB

    MongoDB最基础的东西,我这边就不多说了,这提供罗兄三篇给大家热身 MongoDB初始 MongoDB逻辑与物理存储结构 MongoDB的基础操作 最后对上述内容和关系型数据做个对比 非关系型数据 ...

随机推荐

  1. android sdk无法更新或者更新缓慢的解决方案

    win7安装android sdk老出 Fetching https://dl-ssl.google.com/android/repository/addon .这是android sdk不能连接到谷 ...

  2. 转载 BCS 的好文章 1 - 怎么创建和使用BCS

    http://www.sharepointfabian.com/2010/04/16/how-to-create-configure-consume-sharepoint-2010-secure-st ...

  3. Bit-Coin收入的一分钱

    好吧,这是我在Slush's pool上对Bit-coin收入的第一分钱. 回想起来,2013年平安夜开始到今天,将近3个月没日没夜窝在这个矿里挖矿 从最开始的集成显卡挖,买了显卡挖,加了显卡挖,使用 ...

  4. Mac下利用(xcode)安装git

    Mac下利用(xcode)安装git 一.AppStore 最安全途径:搜索下载Xcode,(需要AppleID). 其他:直接百度Xcode下载. 二.Xcode 打开Xcode-->Pref ...

  5. UnityShader之固定管线Fixed Function Shader【Shader资料3】

    Fixed function shader简介:  属于固定渲染管线 Shader, 基本用于高级Shader在老显卡无法显示时的情况.使用的是ShaderLab语言,语法与微软的FX files 或 ...

  6. ios 删除系统从相册压缩的视频

    iOS的沙盒机制,应用只能访问自己应用目录下的文件.iOS不像android,没有SD卡概念,不能直接访问图像.视频等内容.iOS应用产生的内容,如图像.文件.缓存内容等都必须存储在自己的沙盒内.默认 ...

  7. 关于Socket建立长连接遇到的bug信息

    下面是本人在Socket连接的开发中遇到的bug总结 1."远程服务器关闭了Socket长连接'的错误信息 2.关于"kCFStreamNetworkServiceTypeVoIP ...

  8. Animating Views Using Scenes and Transitions

    From android 4.4 , it supply one new animation with layout:transition To help you animate a change b ...

  9. 解决Android SDK Manager 更新、下载慢以及待安装包列表不显示

    参考地址:http://www.cnblogs.com/tc310/archive/2012/12/21/2828450.html 问题描述: Android SDK Manager 无法下载更新,或 ...

  10. 使用Ant构建struts2 web工程,自动编译,打包成war

    c&c++语言通常使用make脚本来构建和管理自己的工程,同样java也有自己的构建工具(Ant),使用时需要写一个biuld.xml,有点类似c&c++里的makefile. 一.首 ...