WHCSRL 技术网

RC4算法 C语言(从OpenSSL库中分离算法:一)

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",编译选项是:x86Debug

在这里插入图片描述

在这里插入图片描述

三、准备文件

  1. 复制OpenSSL源码中:/crypto/rc4文件夹到VS工程代码目录下
  2. 复制OpenSSL源码中:/include/openssl/rc4.h文件到VS工程代码目录中rc4文件夹内
  3. 复制完成后,VS工程代码目录rc4文件夹内文件如下:

在这里插入图片描述
删除目录内的如下本项目中无用文件:

  • asm
  • build.info
  • rc4_local.h

四、修改代码

修改调用文件

在VS工程中含有main函数的主文件:rc4test.cpp中,增加包含rc4.h头文件

#include "rc4/rc4.h"
  • 1

在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);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

修改后的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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

修改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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

修改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;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76

修改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);
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

五、编译运行

将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;
  • 1
  • 2
  • 3

再次编译运行通过

观察Encrydata,Decrydata内存数据的变化

欢迎大家关注、留言讨论、可分享源码

推荐阅读