简要说明

本设计为湖南大学密码学的一次课程作业设计。非作业目的可随意引用。

由于本人初次接触密码学,本设计可能存在问题以及漏洞。若发现望指出。

GitHub : https://github.com/He11oLiu/SubstitutionCipher

中文utf-8 简单偏移替换密码

初次尝试

中文utf-8的读取

utf-8的格式

UTF-8编码规则:如果只有一个字节则其最高二进制位为0;如果是多字节,其第一个字节从最高位开始,连续的二进制位值为1的个数决定了其编码的位数,其余各字节均以10开头。

获取单个utf-8 编码的长度,注意当最高位为0情况。

int get_utf_8_len(char s){
int i = 0x80,len = 0;
while(s&i) {i=i>>1;len++;}
return len==0?1:len;
}

byte数组中获取单个utf-8 字符

word_length = get_utf_8_len(word_byte[i]);
strncpy(word_utf_8,word_byte+i,word_length);

从3字节utf-8 字符中获取utf-8 编号

int get_utf_8_code(char *s){
return (*s & 0x0F)<<12 | (*(s+1)&0x3F)<<6 |(*(s+2)&0x3F);
}

获取中文字符

常用中文显示范围

U+4e00 - U+9fa5

故利用utf_8_is_cn来判断

#define max_cn_utf_8 0x9fa5
#define min_cn_utf_8 0x4e00
#define cn_utf_8_size (max_cn_utf_8-min_cn_utf_8)
#define utf_8_is_cn(code) (code>=min_cn_utf_8 && code <max_cn_utf_8)

偏移加密测试

/**
* Caesar_cipher_encrpt
* 简单凯撒加密测试,bias为偏移量
* 常用中文大小为cn_utf_8_size
*/
void Caesar_cipher_encrpt(int_32U *plain_code,int_32U *cipher_code,int_32U bias){
*cipher_code = ((*plain_code-min_cn_utf_8)+bias)%cn_utf_8_size + min_cn_utf_8;
} /**
* Caesar_cipher_decrpt
* 简单凯撒解密测试,bias为偏移量
* 常用中文大小为cn_utf_8_size
*/
void Caesar_cipher_decrpt(int_32U *cipher_code,int_32U *plain_code,int_32U bias){
*plain_code = ((*cipher_code+cn_utf_8_size-min_cn_utf_8)-bias)%cn_utf_8_size + min_cn_utf_8;
}

主函数中测试:

if(utf_8_is_cn(utf_8_code)){
Caesar_cipher_encrpt(&utf_8_code,&cipher_code,100);
get_utf_8_word(cipher_code, word_utf_8);
printf("Encrpted: %s ",word_utf_8);
Caesar_cipher_decrpt(&cipher_code,&utf_8_code,100);
get_utf_8_word(utf_8_code, word_utf_8);
printf("Decrpted: %s\n",word_utf_8);
}

测试结果

Encrpted: 云 Decrpted: 中
Encrpted: 旫 Decrpted: 文
Encrpted: 匄 Decrpted: 加
Encrpted: 尪 Decrpted: 密
Encrpted: 涯 Decrpted: 测
Encrpted: 谹 Decrpted: 试

注意 第一部分代码中有部分错误

在进行下面改进的过程中发现,没有用unsigned的话,会导致%为有符号数。

故将原来的int重新定义如下

typedef unsigned int int_32U;
typedef unsigned long long int_64U;

加密解密程序框架设计

~ ./encryption test out
Encrption end!
~ ./decryption out test1
Decryption end!

初版简单偏移替换加密解密见Caesar_cipher中源代码。

替换加密加强

由于中文文字过多,使用完整的密码转换本不再合理。故分析针对每一个明文,可用的因素有以下几点:

  • 类似秘钥的seed
  • 明文所在位置:明文字符所在位置作为一个因素引入,可以防止相同的字替换到相同的字符,尽量避免统计概率的暴露。

搭建起支持变换seed的框架如下:

#define find_bias(seed1,seed2)  generate_bias_simple(seed1,seed2)
typedef unsigned int int_32U;
typedef unsigned long long int_64U;
int generate_bias_simple(int_32U seed1,int_64U seed2);

在传入替换加密解密时,利用生成的bias

bias = find_bias(count,(int_64U)seed_high<<32|seed_low);
Caesar_cipher_decrpt(&utf_8_code,&plain_code,bias);

而最简单的,利用上述两个因素的bias计算如下:

int generate_bias_simple(int_32U seed1,int_64U seed2){
return (seed1*seed2)%cn_utf_8_size;
}

该算法加密主要部分代码

while(!feof(fp_in)){
if(fgets(word_byte,max_len,fp_in)==NULL) continue;
for(i = 0; word_byte[i]!='\0';i = i + word_length){
count ++;
//获取utf-8编码该字长度
word_length = get_utf_8_len(word_byte[i]);
//获取utf-8字,放入word_utf_8中
strncpy(word_utf_8,word_byte+i,word_length);
word_utf_8[word_length] = '\0';
// printf("%s",word_utf_8);
if(word_length == 3) {
//获取当前utf-8字符的utf-8码
utf_8_code = get_utf_8_code(word_byte+i);
//若utf-8为中文 进行加密
if(utf_8_is_cn(utf_8_code)){
bias = find_bias(count,(int_64U)seed_high<<32|seed_low);
//偏移替换加密
Caesar_cipher_encrpt(&utf_8_code,&cipher_code,bias);
//获取utf_8的字
get_utf_8_word(cipher_code, word_utf_8);
fprintf(fp_out,"%s",word_utf_8);
}
else{
fprintf(fp_out,"%s",word_utf_8);
}
}
else
fprintf(fp_out,"%s",word_utf_8);
}
}

该算法解密主要部分代码

while(!feof(fp_in)){
if(fgets(word_byte,max_len,fp_in)==NULL) continue;
for(i = 0; word_byte[i]!='\0' ;i = i + word_length){
count ++;
//获取utf-8编码该字长度
word_length = get_utf_8_len(word_byte[i]);
//获取utf-8字,放入word_utf_8中
strncpy(word_utf_8,word_byte+i,word_length);
word_utf_8[word_length] = '\0';
if(word_length == 3) {
//获取当前utf-8字符的utf-8码
utf_8_code = get_utf_8_code(word_byte+i);
//若utf-8为中文 进行解密
if(utf_8_is_cn(utf_8_code)){
//计算偏移量
bias = find_bias(count,(int_64U)seed_high<<32|seed_low);
//凯撒密码解密部分
Caesar_cipher_decrpt(&utf_8_code,&plain_code,bias);
get_utf_8_word(plain_code, word_utf_8);
fprintf(fp_out,"%s",word_utf_8);
}
else{
fprintf(fp_out,"%s",word_utf_8);
}
}
else
fprintf(fp_out,"%s",word_utf_8);
}
}

加密解密测试

test_txt内容

句子测试:
在密码学中,恺撒密码(英语:Caesar cipher),或称恺撒加密、恺撒变换、变换加密,是一种最简单且最广为人知的加密技术。
相同字符测试:
密密密密密密密密密密密密密密密密密密密密密密密密密密密密密密密密密密密密。

输入命令加密

~ ./encryption test_txt out ab12idhs
Encrption end!

out内容

偮呢酊媸:
鮯禕鉙片迻,魚確汷懺(旼駥:Caesar cipher),嚐饗籪紋阆鮵、瘺盛鄎鴡、捨潻覦轕,澏叩簿鑟參嚅齲捂薮燲滻煮沖玟祎粑媈。
蹐柭騥擘历鳽:
郭赶暾捇忐誽蝆悎崗妠蒍脖綟囧印繝竦睯傷黥砭璶焿鰬颵锾溆欏闼銅輎桖擟慨豕裞。

输入命令解密

~ ./decryption out test_out ab12idhs
Decryption end!

test_out内容

句子测试:
在密码学中,恺撒密码(英语:Caesar cipher),或称恺撒加密、恺撒变换、变换加密,是一种最简单且最广为人知的加密技术。
相同字符测试:
密密密密密密密密密密密密密密密密密密密密密密密密密密密密密密密密密密密密。

若输入秘钥错误 (只错了一位)

~ ./decryption out test_out ab12idhr
Decryption end!

test_out内容

另孒济诙:
圯寎砊孰丸,悇撠寕砑(范谀:Caesar cipher),戺稕悠撹勈寯、悥撾吅掐、合掓勒对,晤丶稄朸箹厏乏朼庼乸仹砥盅勢尉拄杴。
着呕审筱涗谢:
尖尗尘尙尚尛尜尝尞尟尠尡尢尣尤尥尦尧尨尩尪尫尬尭尮尯尰就尲尳尴尵尶尷尸尹。

很明显,在秘钥在只错一位的情况下,已经在正确的明文周围了,下面就来想办法结局一下这个相关性

打乱秘钥与偏移的连续性

由于之前已经写好了整体的框架,这里只需要更改generate_bias_simple函数中的内容。

这次增强的主要原因是,当密钥只有少数几位差距时,乘法所具有的连续性不能够很好的被打乱,所以导致上面密文与原文过于接近。

所以希望能找到一种映射,从连续的秘钥,映射到非连续的秘钥。

经过思考,觉得希望每次所乘秘钥均不同。故设计以下改变seed2的办法。(可能有数学缺陷,先这么设计着,还不知道怎么证明)

  • 右边32-bit等于与左32-bit异或
  • 交换左右部分
  • 循环左移seed1&0x07

测试函数如下:(见key_test.c文件)

int main(int argc, const char * argv[]) {
int_64u s_key = 0xf18283a18c4d5fb1;
int count;
printf("%llx\n",s_key);
for(count = 0; count <100;count ++){
s_key = s_key>>32 | ((int)s_key^(s_key>>32))<<32;
s_key = s_key>>(64-(count&0x7))|s_key << (count&0x7);
printf("%llx\n",s_key);
}
return 0;
}

截取部分如下

11ac4ddcb0ddcedb
42e3060e23589bb9
86ee76dd0b8c1839
6b1377243773b6ec
c60c1c86b1377245
e76dd878c18390ce

由于是移动是0 1 2 … 7 则每次是移动28 bit,且每次均有异或。其循环的周期还是比较大的。

修改产生bias 函数如下:

int generate_bias_advance(int_32U seed1,int_64U seed2){
seed2 = seed2>>32 | ((int)seed2^(seed2>>32))<<32;
seed2 = seed2>>(64-(seed1&0x7))|seed2 << (seed1&0x7);
return (seed2*seed1)%cn_utf_8_size;
}

修改后利用秘钥ab12idhr 解密ab12idhs加密的上面同一段文字,结果为

匧塘摣琕:
儼壎煓鸳缪,楤度爓爑(根厅:Caesar cipher),腅嫉少緥镭軽、萜呁磻门、鎭邩娍枨,緷旐秭券儲仢鏛髹棬鳹欓急韫鏲觍曹摁。
局澃郉酭鏩箌:
辻煍蕘婍勤过婣笥賃歝祸鐲甉艬酒非觋敭涘籲霮甑皜懲蛓彽憸撲枮架實縫菛妍嗘麗。

这次第二排没有明显与位置相关的痕迹了。

性能测试

测试环境

利用2k字的文件进行测试,并在代码中加入统计部分。

~ ./encryption test_2k out ab12idhr
Encrption finish! Count : 1843 Time : 0.000746seconds
Speed : 2469 k per socend
~ ./decryption out test_out ab12idhr
Decryption finish! Count : 1843 Time : 0.000720seconds
Speed : 2558 k per socend

存在的问题 & 改进方向

  • 针对每个字均更改秘钥可能导致效率不够高,可以更改成每一轮更改秘钥。
  • 没有验证数学上的严谨性,可能存在周期性问题,当获取大量明文密文对是可能会受到攻击。
  • 可以在输入秘钥上提供更友好的16进制输入方式。
  • 可以添加加密接口供其他程序使用。

英文 utf-8 替换密码

简要说明

英文utf-8替换密码的设计继承了前文中文的加密,用法与文件目录相同,不再展示说明。

设计内容

设计思路

由于已经完成了utf-8 的中文加密的内容,所有希望能够有足够的兼容性,能够同时加密中文以及英文。故继承了中文加密的算法,只做出了少数改变。

添加英文utf-8 相关宏

#define min_en_utf_8 0x61
#define max_en_utf_8 0x7a
#define en_utf_8_size (max_en_utf_8-min_en_utf_8)
#define utf_8_is_en(code) (code>=min_en_utf_8 && code < max_en_utf_8)

修改偏移量宏,使其能够兼容英文

#define find_bias_cn(seed1,seed2)  generate_bias_advance(seed1,seed2,cn_utf_8_size)
#define find_bias_en(seed1,seed2) generate_bias_advance(seed1,seed2,en_utf_8_size)

增加英文加密解密替换模块

void Caesar_cipher_encrpt_en(int_8U *plain_code,int_8U *cipher_code,int_8U bias){
*cipher_code = ((*plain_code-min_en_utf_8)+bias)%en_utf_8_size + min_en_utf_8;
} void Caesar_cipher_decrpt_en(int_8U *cipher_code,int_8U *plain_code,int_8U bias){
*plain_code = ((*cipher_code+en_utf_8_size-min_en_utf_8)-bias)%en_utf_8_size + min_en_utf_8;
}

增加英文处理模块

else if(word_length == 1){
utf_8_en_code = word_utf_8[0];
if(utf_8_is_en(utf_8_en_code)){
count_work++;
count_en++;
//这里是英语处理
bias = find_bias_en(count_en,(int_64U)seed_high<<32|seed_low);
Caesar_cipher_encrpt_en(&utf_8_en_code,&cipher_en_code,bias);
*word_utf_8 = cipher_en_code;
*(word_utf_8 + 1) = 0x00;
fprintf(fp_out,"%s",word_utf_8);
}
else{
fprintf(fp_out,"%s",word_utf_8);
}
}

测试功能

同中文相同的处理内容,处理结果如下(秘钥ab12idhs):

瓍赋忲躗:
締跁妕軂锻,牴譊崙詒(昉萘:Ceuqvm pfgssl),竨孵短餀藼釁、惫苨鈒郵、枊衭賡廹,巔醳捱嬈愷軷吉遞愴器撞窧鳰辣摽酢瓴。
娐賉馻蚟倌包:
烙莓鮋樁閰羫咯膄儯闤鳬泃鬴誻櫏尟忩蓴鹍澅伓闋胯衟釤靅三片咗伶霏拺爺處佪甉。

性能测试

同样找了一个大约为2k字的测试文档,保存在test_2k,测试环境同中文加密测试,测试结果如下:

~ ./encryption test_2k test_out ab12idhs
StartEncrption finish! Count : 8448 Time : 0.003290seconds
Speed : 2559 k per socend
~ ./decryption test_out test_2k ab12idhs
Decryption finish! Count : 8448 Time : 0.003720seconds
Speed : 2264 k per socend

这个结果可以说明,计算秘钥的函数严重影响了效率

存在的问题

  • 由于英语的字母较少,很容易替换到相同的字母,大大减少了可替换的空间。
  • 为了兼容中文加密,英语也采用中文的比较复杂的算法,导致其速度没有改善。
  • 英文用替换加密实际证明不太靠谱,还是需要结合扩散形成更复杂的分组加密。

基于C语言的UTF-8中英文替换密码设计的更多相关文章

  1. selenium2自动化测试实战--基于Python语言

    自动化测试基础 一. 软件测试分类 1.1 根据项目流程阶段划分软件测试 1.1.1 单元测试 单元测试(或模块测试)是对程序中的单个子程序或具有独立功能的代码段进行测试的过程. 1.1.2 集成测试 ...

  2. 《Selenium2自动化测试实战--基于Python语言》 --即将面市

    发展历程: <selenium_webdriver(python)第一版>   将本博客中的这个系列整理为pdf文档,免费. <selenium_webdriver(python)第 ...

  3. 在云平台上基于Go语言+Google图表API提供二维码生成应用

    二维码能够说已经深深的融入了我们的生活其中.到处可见它的身影:但通常我们都是去扫二维码, 曾经我们分享给朋友一个网址直接把Url发过去,如今我们能够把自己的信息生成二维码再分享给他人. 这里就分享一下 ...

  4. 关于《selenium2自动测试实战--基于Python语言》

    关于本书的类型: 首先在我看来技术书分为两类,一类是“思想”,一类是“操作手册”. 对于思想类的书,一般作者有很多年经验积累,这类书需要细读与品位.高手读了会深有体会,豁然开朗.新手读了不止所云,甚至 ...

  5. Gogs - 基于 Go 语言的自助 Git 服务

    Gogs(Go Git Service) 是一个基于 Go 语言的自助 Git 服务.Gogs 的目标是打造一个最简单.最快速和最轻松的方式搭建自助 Git 服务.使用 Go 语言开发使得 Gogs ...

  6. Ggoogle Protocol Buffer的使用 (基于C++语言)

    首先说明的是Protocol Buffle是灵活高效的.它的一个很好的优点(很重要的,我认为)就是后向兼容性--当我们扩展了了.proto文件后,我们照样可以用它来读取之前生成的文件. 之前已经写了关 ...

  7. 基于C# 语言的两个html解析器

    基于C# 语言的两个html解析器 1)Html Agility Pack http://nsoup.codeplex.com/ 代码段示例: HtmlDocument doc = new HtmlD ...

  8. springmvc国际化 基于浏览器语言的国际化配置

    当前标签: springmvc   springmvc国际化 基于浏览器语言的国际化配置 苏若年 2013-10-09 13:03 阅读:305 评论:0   SpringMVC中应用Ajax异步通讯 ...

  9. 基于JAVA语言的多线程技术

    1.简介 多线程技术属于操作系统范围内的知识: 进程与线程 可以这么理解,一个应用程序就是一个进程,在一个进程中包含至少一个线程:进程就是线程的容器,真正工作.处理任务的是线程. 进程是操作系统分配资 ...

随机推荐

  1. 基于FPGA的Uart接收图像数据至VGA显示

    系统框图 前面我们设计了基于FPGA的静态图片显示,接下来我们来做做基于FPGA的动态图片显示,本实验内容为:由PC端上位机软件通过串口发送一幅图像数据至FPGA,FPGA内部将图像数据存储,最后扫描 ...

  2. 深入理解Spring MVC 思想

    目录  一.前言二.spring mvc 核心类与接口三.spring mvc 核心流程图 四.spring mvc DispatcherServlet说明 五.spring mvc 父子上下文的说明 ...

  3. vue指令v-text示例解析

    <div id="app"> <!--两种方式都是插值,输出结果一样--> <p v-text="msg"></p&g ...

  4. 解决百度BMR的spark集群开启slaves结点的问题

    前言 最近一直忙于和小伙伴倒腾着关于人工智能的比赛,一直都没有时间停下来更新更新我的博客.不过在这一个过程中,遇到了一些问题,我还是记录了下来,等到现在比较空闲了,于是一一整理出来写成博客.希望对于大 ...

  5. SO_REUSEADDR与SO_REUSEPORT平台差异性与测试

    前些天,与另外一个项目组的同事聊天的时候,谈到他遇到的一个有意思的BUG.在window上启动服务器,然后客户端连接的时候收到一些奇怪的消息,查证了,原来是他自己的另一个工具也在相同的地址上监听,客户 ...

  6. Linux - 简明Shell编程01 - 第一个脚本(HelloShell)

    脚本地址 https://github.com/anliven/L-Shell/tree/master/Shell-Basics 示例脚本及注释 #!/bin/bash echo "hell ...

  7. python学习之字符串(上)

    字符串python 的字符串被划归为不可变序列这一类别,意味着这些字符串所包含的字符存在从左至右的位置顺序,并且他们不可以在原处修改. 字符串常量单引号  'spam'双引号  "spam& ...

  8. GDB教程

    GDB是一个由GNU开源组织发布的.UNIX/LINUX操作系统下的.基于命令行的.功能强大的程序调试工具. GDB中的命令固然很多,但我们只需掌握其中十个左右的命令,就大致可以完成日常的基本的程序调 ...

  9. Weex入门指南

    背景 由于公司项目需要,需求变化频繁,计划总改不上变化,由于app更新版本周期长,不能很好应对这种变化,正在此前提下热修复和热更新技术也有了发展的空间,不管热修复还是热更新,都是对app内容或者逻辑的 ...

  10. 一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——实现篇:(四)用户接口层之处理SDP报文

    当RTSP客户端向RTSP服务端发送DESCRIBE命令时,服务端理应当回复一条SDP报文. 该SDP报文中包含RTSP服务端的基本信息.所能提供的音视频媒体类型以及相应的负载能力,以下是一段SDP示 ...