RSA加密/解密长文件

时间:2017-11-07 10:33:50

标签: c encryption cryptography rsa public-key-encryption

我想在openssl / libcrypto中用RSA加密/解密一个长文件(我知道AES更好,但这只是为了比较)。我将输入文件拆分为大小为numBlocks = inputFileLength/maxlen+1的块maxlen = 200。我可以在同一个循环中成功编码和解码如下:

for (int i = 0; i < chunks; i++)
{
    int bytesDone = i * maxlen;
    int remainingLen = inLength - bytesDone;
    int thisLen; 

    if (remainingLen > maxlen)
    {
        thisLen = maxlen;
    } else
    {
        thisLen = remainingLen;
    }
    if((encBytes=RSA_public_encrypt(thisLen, data + bytesDone, encryptdata + bytesDone,
                                    rsa_public, RSA_PKCS1_PADDING)) == -1)
    {
        printf("error\n");
    }
    if((decBytes=RSA_private_decrypt(encBytes, encryptdata + bytesDone, decryptdata + bytesDone,
                                     rsa_private, RSA_PKCS1_PADDING)) == -1)
    {
        printf("error\n");
    }
}

但是,我想将编码缓冲区encryptdata保存在二进制文件中,读回二进制文件并解密。我试着这样做:

 for (int i = 0; i < chunks; i++)
{
    int bytesDone = i * maxlen;
    int remainingLen = inLength - bytesDone;
    int thisLen; 

    if (remainingLen > maxlen)
    {
        thisLen = maxlen;
    } else
    {
        thisLen = remainingLen;
    }
    if((encBytes=RSA_public_encrypt(thisLen, data + bytesDone, encryptdata + bytesDone,
                                    rsa_public, RSA_PKCS1_PADDING)) == -1)
    {
        printf("error\n");
    }

}

writeFile("encoded.bin",encryptdata,strlen(encryptdata));
size_t size;
unsigned char *readData = readFile("encoded.bin", size);
int inputlen = size;
for (int i = 0; (i * keylen) < inputlen; i++) //keylen = 256
{
    int bytesDone = i * keylen;


    if((decBytes=RSA_private_decrypt(encBytes, readData + bytesDone, decryptdata + bytesDone,
                                     rsa_private, RSA_PKCS1_PADDING)) == -1)
    {
        printf("error\n");
    }
}
printf("Decrypted text: %s",decryptdata);

readFilewriteFile函数如下:

void writeFile(char *filename, unsigned char *file, size_t fileLength
{

FILE *fd = fopen(filename, "wb");
if(fd == NULL) {
    fprintf(stderr, "Failed to open file: %s\n", strerror(errno));
    exit(1);
}

size_t bytesWritten = fwrite(file, 1, fileLength, fd);

if(bytesWritten != fileLength) {
    fprintf(stderr, "Failed to write file\n");
    exit(1);
}

fclose(fd);

}

unsigned char* readFile(char *filename, size_t size) {
FILE *fd = fopen(filename, "rb");
if(fd == NULL) {
    fprintf(stderr, "Failed to open file: %s\n", strerror(errno));
    exit(1);
}

// Determine size of the file
fseek(fd, 0, SEEK_END);
size_t fileLength = ftell(fd);
fseek(fd, 0, SEEK_SET);
size = fileLength;
// Allocate space for the file
unsigned char* buffer = (unsigned char*)malloc(fileLength);

// Read the file into the buffer
size_t bytesRead = fread(buffer, 1, fileLength, fd);

if(bytesRead != fileLength) {
    fprintf(stderr, "Error reading file\n");
    exit(1);
}

fclose(fd);

return buffer;

}

但是,解密失败并显示错误消息segmentation fault (core dump),解密函数仅返回每个块的-1。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:2)

ReadFile修改参数&#34; size&#34;这是通过值传递的,因此当readfile函数返回时,大小不受影响。

我会按如下方式更改readfile proto:

unsigned char* readFile(char *filename, size_t *size) 

然后将调用更改为

unsigned char *readData = readFile("encoded.bin", &size);

最后将readFile大小更新修改为

size = fileLength;

答案 1 :(得分:0)

您的代码中存在各种技术错误,例如在此语句中对二进制数据执行strlen(..)

writeFile("encoded.bin",encryptdata,strlen(encryptdata)); 

encryptdata是二进制数据,可以包含0,可以strlen(..)

作为字符串终止进行插播

但主要问题是您尝试使用 RSA 作为分组密码。您加密的块比您加密的块大,但您不能在代码中处理它。您可能能够获得代码来处理此问题,但正确的方法是使用发明用于批量加密的密码,例如 AES 。当您这样做时,您会自动获得对阻止&#39;开箱即用。

除此之外,您还可以获得1000倍的加密速度。