RC4算法 C语言(从OpenSSL库中分离算法:四)
OpenSSL简介:
OpenSSL 是用于传输层安全性 (TLS) 和安全套接字层 (SSL) 协议的一个强大、商业级和功能齐全的工具包,它也是一个通用的密码学库。包含有RSA、SM4、DES、AES等诸多加密算法。
OpenSSL GitHub地址如下:
GitHub - openssl/openssl: TLS/SSL and crypto library
在日常的开发工作中,有时只想用OpenSSL库中的一种算法,此时调用整个OpenSSL库,往往是没必要的;再或者在嵌入式平台使用某一算法,那我们只移植这个算法,没有必要移植整个OpenSSL库。
RC4简介:
RC4是由罗纳德·李维斯特在1987年开发出来的,虽然它的官方名是“Rivest Cipher 4”,但是首字母缩写RC也可以理解为"Ron’s Code"
RC4是一种非常流行的流加密技术。由于加解密使用相同的秘钥,是对称加密算法。且经过RC4加密前后数据长度不变,不分组分块,不用补齐字节,因此在数据传输领域具备很大优势。
一、下载代码
从OpenSSL的Github仓库下载代码,可以下载master分支,也可以下载最新的release版本。将下载的文件解压,得到代码。
重点关注红框目录:
- crypto目录内是各种加密算法
- include目录内是各加密算法对外接口的头文件
二、准备环境
新建Visual Studio C++ 控制台项目"rc4test",编译选项是:x86\Debug
三、准备文件
- 复制OpenSSL源码中:/crypto/rc4文件夹到VS工程代码目录下
- 复制OpenSSL源码中:/include/openssl/rc4.h文件到VS工程代码目录中rc4文件夹内
- 复制完成后,VS工程代码目录rc4文件夹内文件如下:
删除目录内的如下本项目中无用文件:
- asm
- build.info
- rc4_local.h
四、修改代码
修改调用文件
在VS工程中含有main函数的主文件:rc4test.cpp中,增加包含rc4.h头文件
#include "rc4/rc4.h"
在main函数中添加如下代码
const char* Rc4Key = "12345678";
RC4_KEY key;
RC4_set_key(&key, strlen((const char *)Rc4Key), (unsigned char*)Rc4Key);
const char* indata = "ABCG";
unsigned char Encrydata[256] = {0};
RC4(&key, strlen((const char*)indata),(unsigned char*) indata, Encrydata);
unsigned char Decrydata[256] = { 0 };
RC4_KEY key2;
RC4_set_key(&key2, strlen((const char*)Rc4Key), (unsigned char*)Rc4Key);
RC4(&key2, 7, (unsigned char*)Encrydata, Decrydata);
修改后的md5test.cpp代码如下:
#include <iostream>
#include "rc4/rc4.h"
int main()
{
const char* Rc4Key = "12345678";
RC4_KEY key;
RC4_set_key(&key, strlen((const char*)Rc4Key), (unsigned char*)Rc4Key);
const char* indata = "ABCG";
unsigned char Encrydata[256] = { 0 };
RC4(&key, strlen((const char*)indata), (unsigned char*)indata, Encrydata);
unsigned char Decrydata[256] = { 0 };
RC4_KEY key2;
RC4_set_key(&key2, strlen((const char*)Rc4Key), (unsigned char*)Rc4Key);
RC4(&key2, strlen((const char*)Encrydata), (unsigned char*)Encrydata, Decrydata);
}
修改rc4.h
删除条件编译 OPENSSL_RC4_H
删除条件编译 OPENSSL_NO_DEPRECATED_3_0
删除条件编译 OPENSSL_NO_DEPRECATED_3_0
删除条件编译 OPENSSL_NO_RC4
删除头文件# include <openssl/macros.h>
删除头文件# include <openssl/opensslconf.h>
删除函数类型宏OSSL_DEPRECATEDIN_3_0
修改或删除后的文件如下:
# pragma once
# include <stddef.h>
# ifdef __cplusplus
extern "C" {
# endif
typedef struct rc4_key_st {
RC4_INT x, y;
RC4_INT data[256];
} RC4_KEY;
const char *RC4_options(void);
void RC4_set_key(RC4_KEY *key, int len,
const unsigned char *data);
void RC4(RC4_KEY *key, size_t len,
const unsigned char *indata,
unsigned char *outdata);
# ifdef __cplusplus
}
# endif
修改rc4_enc.c
删除头文件# include "internal/deprecated.h"
删除头文件# include "rc4_local.h"
修改头文件# include <openssl/rc4.h>
改为#include "rc4.h"
修改或删除后的文件如下:
#include "rc4.h"
/*-
* RC4 as implemented from a posting from
* Newsgroups: sci.crypt
* Subject: RC4 Algorithm revealed.
* Message-ID: <sternCvKL4B.Hyy@netcom.com>
* Date: Wed, 14 Sep 1994 06:35:31 GMT
*/
void RC4(RC4_KEY *key, size_t len, const unsigned char *indata,
unsigned char *outdata)
{
register RC4_INT *d;
register RC4_INT x, y, tx, ty;
size_t i;
x = key->x;
y = key->y;
d = key->data;
#define LOOP(in,out) \
x=((x+1)&0xff); \
tx=d[x]; \
y=(tx+y)&0xff; \
d[x]=ty=d[y]; \
d[y]=tx; \
(out) = d[(tx+ty)&0xff]^ (in);
i = len >> 3;
if (i) {
for (;;) {
LOOP(indata[0], outdata[0]);
LOOP(indata[1], outdata[1]);
LOOP(indata[2], outdata[2]);
LOOP(indata[3], outdata[3]);
LOOP(indata[4], outdata[4]);
LOOP(indata[5], outdata[5]);
LOOP(indata[6], outdata[6]);
LOOP(indata[7], outdata[7]);
indata += 8;
outdata += 8;
if (--i == 0)
break;
}
}
i = len & 0x07;
if (i) {
for (;;) {
LOOP(indata[0], outdata[0]);
if (--i == 0)
break;
LOOP(indata[1], outdata[1]);
if (--i == 0)
break;
LOOP(indata[2], outdata[2]);
if (--i == 0)
break;
LOOP(indata[3], outdata[3]);
if (--i == 0)
break;
LOOP(indata[4], outdata[4]);
if (--i == 0)
break;
LOOP(indata[5], outdata[5]);
if (--i == 0)
break;
LOOP(indata[6], outdata[6]);
if (--i == 0)
break;
}
}
key->x = x;
key->y = y;
}
修改rc4_skey.c
删除头文件# include "internal/deprecated.h"
修改头文件# include <openssl/rc4.h>
改为#include "rc4.h"
删除头文件# include "rc4_local.h"
删除头文件#include <openssl/opensslv.h>
修改或删除后的文件如下:
#include "rc4.h"
const char *RC4_options(void)
{
if (sizeof(RC4_INT) == 1)
return "rc4(char)";
else
return "rc4(int)";
}
/*-
* RC4 as implemented from a posting from
* Newsgroups: sci.crypt
* Subject: RC4 Algorithm revealed.
* Message-ID: <sternCvKL4B.Hyy@netcom.com>
* Date: Wed, 14 Sep 1994 06:35:31 GMT
*/
void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data)
{
register RC4_INT tmp;
register int id1, id2;
register RC4_INT *d;
unsigned int i;
d = &(key->data[0]);
key->x = 0;
key->y = 0;
id1 = id2 = 0;
#define SK_LOOP(d,n) { \
tmp=d[(n)]; \
id2 = (data[id1] + tmp + id2) & 0xff; \
if (++id1 == len) id1=0; \
d[(n)]=d[id2]; \
d[id2]=tmp; }
for (i = 0; i < 256; i++)
d[i] = i;
for (i = 0; i < 256; i += 4) {
SK_LOOP(d, i + 0);
SK_LOOP(d, i + 1);
SK_LOOP(d, i + 2);
SK_LOOP(d, i + 3);
}
}
五、编译运行
将rc4.h,rc4_enc.c,rc4_skey.c文件,配置添加到VS工程中。
编译,此时会报错,VS定位在rc4.h中的,结构体rc4_key_st声明,原因是RC4_INT类型是不存在的,且没有经过定义。这个RC4_INT是整个OpenSSL项目编译时,有Perl脚本根据配置文件和参数生成的,我们这里只需要在结构体声明之前,对RC4_INT进行定义如下:
typedef int RC4_INT;
//或
typedef unsigned char RC4_INT;
再次编译运行通过
观察Encrydata,Decrydata内存数据的变化
欢迎大家关注、留言讨论、可分享源码