怎么在ios进行rsa公钥加密,java做rsa私钥解密

Python052

怎么在ios进行rsa公钥加密,java做rsa私钥解密,第1张

KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA")keyGen.initialize(1024)KeyPair key = keyGen.generateKeyPair()Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding")//把第二个参数改为 key.getPrivate()cipher.init(Cipher.ENCRYPT_MODE, key.getPublic())byte[] cipherText = cipher.doFinal("Message".getBytes("UTF8"))System.out.println(new String(cipherText, "UTF8"))//把第二个参数改为key.getPublic()cipher.init(Cipher.DECRYPT_MODE, key.getPrivate())byte[] newPlainText = cipher.doFinal(cipherText)System.out.println(new String(newPlainText, "UTF8"))正常的用公钥加密私钥解密就是这个过程,如果按私钥加密公钥解密,只要按备注改2个参数就可以。但是我要提醒楼主,你要公钥解密,公钥是公开的,相当于任何人都查到公钥可以解密。你是想做签名是吧。

了之前三个终端进行AES加解密的经验,实现RSA加解密倒不是太复杂。两个关键点:1)RSA需要密钥文件,且密钥文件的格式很重要;2)padding方式需要一致,比较被广泛支持且被很多RAS实现设置为默认padding方式的是PKCS1PADDING V1.5,建议采用。

我是在linux下用openssl生成公钥、私钥文件的,分三个步骤,命令如下:

1、生成公钥public_key.der 和 私钥private_key.pem(加密)

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客户端进行公钥加密。

2、生成公钥public_key.pem。

openssl rsa -in private_key.pem -pubout -out public_key.pem ,这步生成的public_key.pem用于分发到c++客户端和安卓客户端进行公钥加密。

3、将私钥 private_key.pem(加密)转换为PKCS#8编码格式(且不加密)。

openssl pkcs8 -topk8 -in private_key.pem -out pkcs8_private_key.pem -nocrypt

这步生成的pkcs8_private_key.pem用于在Java服务端进行私钥解密。

RSA的一般用法是在客户端用公钥加密,在网络上传输密文,然后服务端用私钥解密获取原文。所以RSA实现都会支持公钥加密、私钥解密。反过来用私钥加密然后公钥解密,理论上也是可行的。不过我没有试过。如果决定要这么做,祝君好运。

注意:RSA提供的API不像AES,不会自动分块处理。需要手动将原文切割为128-11的块去进行加密 (128是因为采用RSA1024,128=1024/8, 11是因为padding采用版本1.5的PKCS1PADDING。这种分块方式是多个RSA实现的默认方式,推荐使用),每次加密输出的密文长度均是128字节(RSA1024),把这些密文顺序拼装起来。在解密的时候,则是将密文按128字节进行切割,解密后再拼装在一起即可。

======================C++客户端公钥加密=======================

使用大名鼎鼎openssl类库实现,感慨下其API设计得真烂。。。。

注意:虽然输入和输出都是std::string,但不要理解成字符串,实际上都是二进制数据。另外公钥得保存在文件中,我还没找到使用内存中公钥的方法,但对我已经够用了。

std::string EvpHelper::rsaEncryptUsingPublicKeyFile(const std::string&source, const std::string&keyFile)

{

std::string result

BIO* bp = NULL

EVP_PKEY* key = NULL

RSA* rsa = NULL

EVP_PKEY_CTX* ctx = NULL

unsigned char* encryptedData = NULL

try

{

// load public key

OpenSSL_add_all_algorithms()

bp = BIO_new(BIO_s_file())

if (bp == NULL)

{

throw std::runtime_error("BIO_new failed.")

}

if (BIO_read_filename(bp, keyFile.c_str()) <= 0)

{

throw std::runtime_error("BIO_read_filename failed.")

}

rsa = PEM_read_bio_RSA_PUBKEY(bp, NULL, NULL, NULL)

if (rsa == NULL)

{

throw std::runtime_error("PEM_read_bio_RSA_PUBKEY failed.")

}

key = EVP_PKEY_new()

if (key == NULL)

{

throw std::runtime_error("EVP_PKEY_new failed.")

}

EVP_PKEY_assign_RSA(key, rsa)

rsa = NULL

// encrypt

OpenSSL_add_all_ciphers()

ctx = EVP_PKEY_CTX_new(key, NULL)

if (ctx == NULL)

{

throw std::runtime_error("EVP_PKEY_CTX_new failed.")

}

if (EVP_PKEY_encrypt_init(ctx) <= 0)

{

throw std::runtime_error("EVP_PKEY_encrypt_init failed.")

}

if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0)

{

throw std::runtime_error("EVP_PKEY_CTX_set_rsa_padding failed.")

}

encryptedData = new unsigned char[source.size() * 2]

size_t encryptedDataLen = 0

size_t BLOCK_SIZE = 128 - 11

size_t sourceDataLen = (int)source.size()

for (size_t i = 0i <sourceDataLeni += BLOCK_SIZE)

{

size_t leftBytes = sourceDataLen - i

size_t sourceBlockLen = (leftBytes <= BLOCK_SIZE) ? leftBytes : BLOCK_SIZE

size_t encryptedBlockLen = 128

if(EVP_PKEY_encrypt(ctx, (encryptedData + encryptedDataLen), &encryptedBlockLen,

(const unsigned char *)(source.data() + i), sourceBlockLen) <= 0)

{

throw std::runtime_error("EVP_PKEY_encrypt failed.")

}

encryptedDataLen += encryptedBlockLen

}

result = std::string((char*)encryptedData, encryptedDataLen)

}

catch (const std::exception&e)

{

LErr(e.what())

}

if (bp != NULL)

{

LInfoCMD(BIO_free(bp))

}

if(rsa != NULL)

{

LInfoCMD(RSA_free(rsa))

}

if (ctx != NULL)

{

LInfoCMD(EVP_PKEY_CTX_free(ctx))

}

if (key != NULL)

{

LInfoCMD(EVP_PKEY_free(key))

}

if (encryptedData != NULL)

{

delete[] encryptedData

}

return result

}

======================Java客户端公钥加密=======================

import java.io.BufferedReader

import java.io.FileInputStream

import java.io.FileOutputStream

import java.io.InputStreamReader

import java.security.KeyFactory

import java.security.interfaces.RSAPublicKey

import java.security.spec.X509EncodedKeySpec

import javax.crypto.Cipher

import org.apache.commons.codec.binary.Base64

public class RSAEncrypt {

public static RSAPublicKey loadPublicKeyFromFile(String keyPath)

throws Exception {

BufferedReader br = null

StringBuilder sb = new StringBuilder()

try {

br = new BufferedReader(new InputStreamReader(new FileInputStream(

keyPath)))

String line = null

while ((line = br.readLine()) != null) {

if (line.charAt(0) == '-') {

continue

} else {

sb.append(line)

sb.append('\r')

}

}

} finally {

if (br != null) {

br.close()

}

}

return loadPublicKey(sb.toString())

}

public static RSAPublicKey loadPublicKey(String publicKeyStr)

throws Exception {

Base64 decoder = new Base64()

byte[] buffer = decoder.decode(publicKeyStr)

KeyFactory keyFactory = KeyFactory.getInstance("RSA")

X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer)

return (RSAPublicKey) keyFactory.generatePublic(keySpec)

}

public static void main(String[] args) throws Exception {

RSAPublicKey publicKey = loadPublicKeyFromFile("public_key.pem")

Cipher cipher = Cipher.getInstance("RSA")

cipher.init(Cipher.ENCRYPT_MODE, publicKey)

byte[] rawText = CommonUtil.readFileContents("from.txt")

FileOutputStream out = null

try {

out = new FileOutputStream("java_out.bin")

int BLOCK_SIZE = 128 - 11

for (int i = 0i <rawText.lengthi += BLOCK_SIZE) {

int leftBytes = rawText.length - i

int length = (leftBytes <= BLOCK_SIZE) ? leftBytes : BLOCK_SIZE

out.write(cipher.doFinal(rawText, i, length))

}

} finally {

if (out != null) {

out.close()

}

}

}

}

======================IOS客户端公钥加密=======================

static SecKeyRef _public_key = nil

- (SecKeyRef) getPublicKey{

if (_public_key == nil){

NSString* filePath = [[NSBundle mainBundle] pathForResource:@"public_key" ofType:@"der"]

NSData* certificateData = [NSData dataWithContentsOfFile:filePath]

SecCertificateRef myCertificate = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)certificateData)

if (myCertificate == nil) {

LErr(@"无法读取公钥内容")

return nil

}

SecPolicyRef myPolicy = SecPolicyCreateBasicX509()

SecTrustRef myTrust

OSStatus status = SecTrustCreateWithCertificates(myCertificate,myPolicy,&myTrust)

SecTrustResultType trustResult

if (status == noErr) {

status = SecTrustEvaluate(myTrust, &trustResult)

}else{

return nil

}

_public_key = SecTrustCopyPublicKey(myTrust)

CFRelease(myCertificate)

CFRelease(myPolicy)

CFRelease(myTrust)

}

return _public_key

}

- (NSData*) rsaEncrypt:(NSData*) data{

SecKeyRef key = [self getPublicKey]

if (key == nil) {

return nil

}

size_t cipherBufferSize = SecKeyGetBlockSize(key)

uint8_t* cipherBuffer = malloc(cipherBufferSize * sizeof(uint8_t))

size_t blockSize = cipherBufferSize - 11

size_t blockCount = (size_t)ceil([data length] / (double)blockSize)

NSMutableData *encryptedData = [[NSMutableData alloc] init]

for (int i=0i

int bufferSize = (int)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){

NSData *encryptedBytes = [[NSData alloc] initWithBytes:(const void *)cipherBuffer length:cipherBufferSize]

[encryptedData appendData:encryptedBytes]

}else{

if (cipherBuffer) free(cipherBuffer)

return nil

}

}

1. 如果后台是java,就将私钥转成PKCS8格式的,转换方法网上一大把,最简单就是用支付宝官网的 RSA签名验签工具 咯,诺,直接把私钥弄进来点转PKCS8带走

2. 如果后台是非java,就将不能这么干了,这个时候就得把支付宝demo里的RSADataSigner工具里formatPrivateKey方法改改,改成-----BEGIN RSA PRIVATE KEY-----\n 支付宝demo里是-----BEGIN PRIVATE KEY-----\n,END同理

OK 解决