一、前言
看了网上在RSA加密解密,给出的例子中都是只能对很小的一段内容进行加密和解密,如果超出了一定的长度加解密程序机会出错。
例:采用公钥加密私钥解密,给出的key是1024bit的话,一次性只能加密117个字节块,如果不足117块按117块处理返回的是128块加密密文,那么对应私钥解密只能解密128字节块,得出的明文是117字节块。key转换具体加密字节块公式
二、编译Openssl
参考 openssl编译
三、C/C++示例程序
enum CryptoType
{
PRIVATE_ENCRYPT = 0,
PRIVATE_DECRYPT,
PUBLIC_ENCRYPT,
PUBLIC_DECRYPT,
};
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "openssl/evp.h"
#include "openssl/bio.h"
#include "openssl/buffer.h"
#include "openssl/rsa.h"
#include "openssl/pem.h"
#include "openssl/err.h"
#include "rsa.h"
static RSA * createRSA(unsigned char * key,int public)
{
RSA *rsa= NULL;
BIO *keybio ;
keybio = BIO_new_mem_buf(key, -1);
if (keybio==NULL)
{
printf( "Failed to create key BIO\n");
goto CREATERSA_FREE;
}
if(public)
{
rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa,NULL, NULL);
}
else
{
rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa,NULL, NULL);
}
if(rsa == NULL)
{
printf( "Failed to PEM_read_bio_RSA\n");
goto CREATERSA_FREE;
}
CREATERSA_FREE:
if(keybio)
BIO_free(keybio);
return rsa;
}
int RSACrypto(unsigned char *key,unsigned char *in,unsigned char *out,int inlen,enum CryptoType type)
{
int ret = 0;
int inOffset = 0;
int outOffset = 0;
int inputLen = inlen;
int maxBlockLen = 0;
int keyBit = 1024;
int padding = RSA_PKCS1_PADDING;
RSA * rsa = createRSA(key,type/2);
if(rsa == NULL)
{
ret = -1;
goto RSACRYPTO_FREE;
}
int rsaLen = RSA_size(rsa);
printf("rsaLen:%d\n",rsaLen);
printf("type:%d\n",type);
//判断key是多少位的
//对于512bit的密钥, block length = 512/8 – 11 = 53 字节 64
//对于1024bit的密钥, block length = 1024/8 - 11 = 117 字节 128
//maxBlockLen = keyBit/8 - 11;
switch(type)
{
case PUBLIC_ENCRYPT:
{
maxBlockLen = keyBit/8 - 11; //117
while(inputLen - inOffset > 0)
{
if(inputLen - inOffset > maxBlockLen)
{
ret = RSA_public_encrypt(maxBlockLen,in + inOffset,out + outOffset,rsa,padding);
inOffset += maxBlockLen;
outOffset += ret;
printf("ret:%d,inOffset:%d\n",ret,inOffset);
}
else
{
ret = RSA_public_encrypt(inputLen - inOffset,in + inOffset,out + outOffset,rsa,padding);
inOffset += (inputLen - inOffset);
outOffset += ret;
printf("ret:%d,inOffset:%d\n",ret,inOffset);
}
}
break;
}
case PUBLIC_DECRYPT:
{
maxBlockLen = keyBit/8;
while(inputLen - inOffset > 0)
{
if(inputLen - inOffset > maxBlockLen)
{
ret = RSA_public_decrypt(maxBlockLen,in + inOffset,out + outOffset,rsa,padding);
inOffset += maxBlockLen;
outOffset += ret;
printf("ret:%d,inOffset:%d\n",ret,inOffset);
}
else
{
ret = RSA_public_decrypt(inputLen - inOffset,in + inOffset,out + outOffset,rsa,padding);
inOffset += (inputLen - inOffset);
outOffset += ret;
printf("ret:%d,inOffset:%d\n",ret,inOffset);
}
}
break;
}
case PRIVATE_ENCRYPT:
{
maxBlockLen = keyBit/8 - 11;
while(inputLen - inOffset > 0)
{
if(inputLen - inOffset > maxBlockLen)
{
ret = RSA_private_encrypt(maxBlockLen,in + inOffset,out + outOffset,rsa,padding);
inOffset += maxBlockLen;
outOffset += ret;
printf("ret:%d,inOffset:%d\n",ret,inOffset);
}
else
{
ret = RSA_private_encrypt(inputLen - inOffset,in + inOffset,out + outOffset,rsa,padding);
inOffset += (inputLen - inOffset);
outOffset += ret;
printf("ret:%d,inOffset:%d\n",ret,inOffset);
}
}
break;
}
case PRIVATE_DECRYPT:
{
maxBlockLen = keyBit/8; //128
while(inputLen - inOffset > 0)
{
if(inputLen - inOffset > maxBlockLen)
{
ret = RSA_private_decrypt(maxBlockLen,in + inOffset,out + outOffset,rsa,padding);
inOffset += maxBlockLen;
outOffset += ret;
printf("ret:%d,inOffset:%d\n",ret,inOffset);
}
else
{
ret = RSA_private_decrypt(inputLen - inOffset,in + inOffset,out + outOffset,rsa,padding);
inOffset += (inputLen - inOffset);
outOffset += ret;
printf("ret:%d,inOffset:%d\n",ret,inOffset);
}
}
break;
}
default:
{
ret = -1;
goto RSACRYPTO_FREE;
}
}
printf("[inOffset:%d,outOffset:%d,maxBlockLen:%d]\n",inOffset,outOffset,maxBlockLen);
RSACRYPTO_FREE:
if(rsa)
RSA_free(rsa);
return outOffset;
}
示例结果
[root@linux]/# ./test
DataLen:148,allocLen:256
rsaLen:128
type:2
ret:128,inOffset:117
ret:128,inOffset:148
[inOffset:148,outOffset:256,maxBlockLen:117]
ret =256
pbase64Encrypt:EI6I16CylRKmdb/XdGxHLCripZoUxgLZK3G1BJNGkOhdVFKUyiKz12385vLzjOg43zAaojEaJO7Z4VAoo7psy/GCbR7lweSkjMrUd+fCzWxuV7RtJcnLXyOTyeALSTDR3HVDoa0AbRdwoRwyrj8xNa+TWtKCIaLBU2K5uRoEMjGnvpGwM3H7xxNp9eGSYROKsspsb2eeXJ1kbhZIiwAdVXx4rRX6m9o9qQ0aPpB/IPx71PfMqfn7MS3DDxjovvNiJ9xOm5lEFoO/GTuAOwx84y+OjJ3w+sR2MnBnFQyx0qH6PIG5fMHYO6EVcHKk2MngDryqCAb1f6Q22gl5ZXUu9A==
decodeLen:256
rsaLen:128
type:1
ret:117,inOffset:128
ret:31,inOffset:256
[inOffset:256,outOffset:148,maxBlockLen:128]
ret:148,pDecode:1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
[root@linux]/#