OpenSSL解决长字节公私钥加解密问题

一、前言

看了网上在RSA加密解密,给出的例子中都是只能对很小的一段内容进行加密和解密,如果超出了一定的长度加解密程序机会出错。
例:采用公钥加密私钥解密,给出的key是1024bit的话,一次性只能加密117个字节块,如果不足117块按117块处理返回的是128块加密密文,那么对应私钥解密只能解密128字节块,得出的明文是117字节块。key转换具体加密字节块公式

借鉴:JAVA解决126字节解密问题

二、编译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]/# 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值