代码下载链接:Socket_Tcp

原文链接:https://blog.csdn.net/weixin_45746588/article/details/107683901

这是一个课程的作业,我是初学者,所以写完这个代码还是花了我好几周的时间,在这里整理下,如有错误请批评指正。

仅供学习参考!

文件传输系统设计

1. Socket通信

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

socket()函数
int socket(int domain, int type, int protocol);

socket()用于创建一个socket描述符(socket descriptor),它唯一标识一个socket。这个socket描述字跟文件描述字一样,后续的操作都有用到它,把它作为参数,通过它来进行一些读写操作。

socket函数的三个参数分别为:

domain:即协议域,又称为协议族(family)。常用的协议族有,AF_INET、AF_INET6、AF_LOCAL(或称AF_UNIX,Unix域socket)、AF_ROUTE等等。协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。

type:指定socket类型。常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等。

protocol:故名思意,就是指定协议。常用的协议有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。

TCP通信

tcp 编程一般的步骤:

2. 文件传输

文件发送将文件进行分片传输,每次传输不大于4096字节。

1.   file_length = File_Length(fr); //得到文件大小
2.  n = (file_length%DEFAULT_BUFFER)?
3.            ((file_length/DEFAULT_BUFFER)+1):(file_length/DEFAULT_BUFFER);//对文件进行切片,每4096字节一片
4.  rmd = (file_length%DEFAULT_BUFFER)?(file_length%DEFAULT_BUFFER):DEFAULT_BUFFER; //剩余最后一片长度的字节

每一片文件信息传输包的格式定义如下:

1.   typedef struct {
2.      int  file_tag;  //是否最后一片标志位
3.      int  file_rmd;  //最后一片文件字节长度
4.      char buffer[DEFAULT_BUFFER];  //要发送的文件字节
5.  }File_Info;

若发送的文件大小是4096个字节,则file_tag=0; file_rmd=0;
若发送的文件为最后一片,则file_tag=1; file_rmd=rmd;

1.   fread(file_packet.buffer, 1, DEFAULT_BUFFER, fr);
2.          if(i!=n)
3.              file_packet.file_tag = 0; file_packet.file_rmd = 0;
4.          else
5.              file_packet.file_tag = 1; file_packet.file_rmd = rmd;
6.          sendto(sock, (char *)&file_packet, sizeof(file_packet), 0,
7.              (struct sockaddr far *)&raddr, sizeof(raddr));

文件接收:接收到文件并直接保存。

1.   recv(udp_receiver, (char *)&file_packet, sizeof(File_Info), 0);
2.        if (file_packet.file_tag == 0)  //是否最后一片标志位
3.            fwrite(file_packet.buffer, 1, DEFAULT_BUFFER, fp);  //非最后一片接收4096字节
4.        else
5.        {
6.            fwrite(file_packet.buffer, 1, file_packet.file_rmd, fp);  //最后一片接收rmd个字节
7.            break;
8.        }

3. RSA加密

RSA加解密公式
加密:公钥(E,N) 密文=(明文^E) mod N
解密:密钥(D,N) 明文=(密文^D) mod N
RSA的安全基于大数分解的难度。公钥和私钥是一对大素数的函数。从一个公钥和密文恢复出明文的难度,等价于分解两个大素数之积。

RSA密钥产生的过程:

  1. 随机选择两个不相等的质数p和q。
  2. 计算p和q的乘积n,n=pq。
  3. 计算n的欧拉函数φ(n)。
  4. 随机选择一个整数e,条件是1<e<φ(n),并且e与φ(n)互质。
  5. 计算e对于φ(n)的模反元素d,使de=1 mod φ(n) ——(de)modφ(n)=1
  6. 产生公钥(e,n)。私钥(d,n)
举例:
  1. 选择p=3,q=11.
  2. n=pq=33.
  3. φ(n)=(p-1)x(q-1)=20.
  4. 选择e=3,e与φ(n)互质
  5. (de)mod φ(n)=(d3)mod20,d=7
  6. 公钥(3,33),私钥(7,33)
    设计过程:密钥产生,由于对文件加密为逐字节加密,因此n的值要大于256。所以p和q的值要大于16。又为了使一个字节加密后的大小小于0xFFFF,则p和q的值要小于256。
1.   void RSA::ProduceKeys() {
2.      long prime1 = ProducePrime();//随机选取16-256之间的素数
3.      long prime2 = ProducePrime();//随机选取16-256之间的素数
4.      while (prime1 == prime2)
5.          prime2 = ProducePrime();//确保两素数不相等
6.      _key.share_key = ProduceShareKey(prime1, prime2);
7.      long orla = ProduceOrla(prime1, prime2);
8.      _key.public_key = ProducePublicKey(orla);   //产生公钥
9.      _key.private_key = ProducePrivateKey(_key.public_key, orla);  //产生私钥
10. }
RSA加密解密:
1.   long RSA::Ecrept(long msg, long key, long share_key) {
2.      unsigned long a = (unsigned long)msg;//msg为要加密或解密的信息
3.      long b = key;
4.      int c = share_key;
5.      long r = 1;
6.      while (b-- != 0)
7.          r = (r * a) % c;
8.      return r;
9.  }

对文件进行加密解密:对文件加密时,读取文件为单字节读取,存储为long类型:

1.   fread(buffer, sizeof(char), DEFAULT_BUFFER, fp); //对字节加密
2.  fwrite(dat, sizeof(long), DEFAULT_BUFFER, save_fp); //存储为long类型

对文件解密时,读取为long类型,储存为char类型:

1.   fread(buffer, sizeof(long), DEFAULT_BUFFER, fp); //对long类型解密
2.  fwrite(dat, sizeof(char), DEFAULT_BUFFER, save_fp); //存储为char类型

4. MD5生成摘要

MD5消息摘要算法,属Hash算法一类。MD5算法对输入任意长度的消息进行运行,产生一个128位的消息摘要。MD5的算法原理为以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
对文件生成摘要:将文件以二进制打开,这里仅对大小不超过4096字节的文件进行加密,若文件大于4096字节,则仅加密前4096字节。

1.   fp = fopen(file_dir, "rb"); //  打开要加密的文件
2.  fr = fopen("client_signature_cache.dat", "w+b");  //打开保存摘要的文件
3.  memset(buffer, 0, DEFAULT_BUFFER);
4.  fread(buffer, sizeof(char), DEFAULT_BUFFER, fp);
5.  getMD5Code(buffer, signature);  //生成数字摘要
6.  fwrite(signature, sizeof(char), 16, fr);  //保存数字摘要到文件

5. 数字签名和身份鉴定

数字签名(又称公钥数字签名)是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。它是一种类似写在纸上的普通的物理签名,但是使用了公钥加密领域的技术来实现的,用于鉴别数字信息的方法。一套数字签名通常定义两种互补的运算,一个用于签名,另一个用于验证。数字签名是非对称密钥加密技术与数字摘要技术的应用。当客户端要向服务器传输文件时,客户端先用MD5算法对将要发送的文件生成数字摘要,然后用自己的私钥对摘要进行加密得到数字签名。客户端将数字签名随文件一起发给服务器,服务器收到文件和数字签名后,首先用公钥将数字签名进行解密得到客户端发送的摘要,再用MD5算法对接收到的文件生成摘要。最后将两份摘要进行对比,若完全一致,说明是客户端发送的文件,并且文件没有被篡改。若不是一致的,则说明文件被篡改或则不是指定客户端发送的,用户被冒用了。

1.   //客户端私钥加密数字摘要得到数字签名
2.  rsa.Ecrept("client_signature_cache.dat", "client_signature_Ecrept.dat", key.private_key, key.share_key);
1.  //服务器公钥解密数字签名得到文件的数字摘要
2.  sa.DEcrept("server_signature_recevie.dat","server_signature_DEcrept.dat",key.public_key,key.share_key);

6. 程序设计及运行

6.1. 与服务器连接并登录

首先开启服务器并监听。打开客户端,客户端会生成一对密钥。输入密码,客户端与服务器建立连接。客户端将公钥发给服务器。运行界面如下图所示:

6.2. List命令获得文件目录

我们已准备两个文件夹,一个是服务器文件夹,一个是客户端文件夹。在客户端输入l或list命令可以得到服务器文件夹下的文件目录。如图所示:

6.3. get命令从服务器下载文件,并加密传输

我们使用get或g命令从服务器下载文件,在文件传输过程中会服务器端会生成加密文件,然后将加密的文件传输给客户端,客户端接收到加密的文件后先缓存,待接收完毕后进行解密,最终得到要下载的文件,并且我们可以看到文件也没有被损坏。运行如下图:

6.4. delet命令从服务器端删除文件

使用delet或d命令可以从服务器文件夹下删除文件,运行如下图:

6.5. put命令上传文件

使用put命令可以上传文件,上传时先将文件生成摘要,再对摘要进行私钥加密。服务器收到文件和摘要后,同样对接收到的文件生成摘要,并对签名使用公钥进行解密。验证两份摘要是否一致。运行结果如下:

文件生成的摘要是:9be686ad1f4e1438ef5bc6ec7ad107d7
我们改变文件的一个字符再次上传,可以看到仅改变一个字符,生成的摘要就完全不一样,得到如下结果:

6.6. help命令和echo命令

输入help命令可以打印帮助页,echo命令可以从服务器得到文件的详细信息。运行如图:

一个课程的作业,我是初学者,所以写完这个代码还是花了我好几周的时间,在这里整理下,如有错误请批评指正。

仅供学习参考!

代码下载链接:Socket_Tcp

Socket_Tcp加密文件传输系统相关推荐

  1. 互联网行业-镭速文件传输系统方案

    互联网行业是一个快速变化和高度竞争的行业,这一行业需要传输大量的数据.代码和文件.在互联网企业的生产和运营过程中,需要传输各种敏感和大型的文件,例如业务报告.数据分析.软件代码等.这些文件需要在不同的 ...

  2. linux密码加密文件,Linux下加密/解密及用密码保护文件的七把利器

    加密是指对文件进行编码的过程,那样只有有权访问的人才可以访问文件.人类早在计算机还没有问世的时候就开始使用加密了.战争期间,人类会传输只有其部落或相关人员才能理解的某种信息. 作者:布加迪/编译来源: ...

  3. 过滤驱动加密文件(代码)

    摘要:     我想做一个unlocker一样的程序,不管这个文件有没有被使用,先实现删除它.在查资料过程中,就知道了如果不访问磁盘扇区的话,除非写驱动才能做到.奈何时间有限,工作匆忙,一直没有完成. ...

  4. Lync 小技巧-24-PDF 加密文件-转-Word-操作手册

    作者:刘金丰 时间:2012-10-07 19:25 目的: 1) 为了大家更好学习. 2) 清除PDF加密文件的密码. 3) 转换PDF为Word. A)参照本文后面的方法. B)可以直接使用Wor ...

  5. linux文件夹加密访问,技术|Linux系统上用encfs创建和管理加密文件夹

    如果你想使你计算机上的某些信息免于被窥视的话,可以看看这篇文字.保护信息的一种方法就是加密你的home目录,但是一旦你登录系统后,你的home目录下的信息将暴露于外.过去,我已经写过关于怎样在你的系统 ...

  6. web主题公园版权信息破解:script.js加密文件

    很多人会使用web主题公园网站的免费worldpress主题,但它的主题又都被加了版权信息,故意让人找不到版权信息的修改位置. 你如果去footer.php里面删除版权信息(技术支持:web主题公园) ...

  7. 【C 语言】文件操作 ( 文件加密解密 | 加密文件 )

    文章目录 一.文件加密解密操作 1.加密整 4096 字节的数据 2.加密小于 4096 字节的数据 二.完整代码示例 1.文件加密操作 2.DES 加密解密头文件 3.第三方 DES 加密解密函数库 ...

  8. 肝!用 Python 加密文件

    生活中,有时候我们需要对一些重要的文件进行加密,Python 提供了诸如 hashlib,base64 等便于使用的加密库. 但对于日常学习而言,我们可以借助异或操作,实现一个简单的文件加密程序,从而 ...

  9. 使用 gpg 加密文件 - 通过 shell 或 php

    使用 gpg 加密文件 - 通过 shell 或 php 背景:客户提供私钥,并要求我方通过php把加密后的文件传输给他们. 环境 macOS Sierra 10.12.1 php 7.0.8 0.安 ...

最新文章

  1. 爱可可推荐!关于竞赛思路,方法和代码实践,Datawhale数据竞赛Baseline开源分享!...
  2. Introspection
  3. SAP SM37后台作业结果显示为alv list怎么样可以显示alv grid形式呢?
  4. 二维数组 类型_「初识C语言」二维数组
  5. 云原生的本质_云原生是什么 云原生技术有何作用
  6. 跨时钟域电路设计——单bit信号
  7. 【NOI2019】 机器人 【区间dp】【插值】【下降幂多项式】【分段函数】
  8. python语句join_Python中的join()函数的用法
  9. Eric Brewer大神
  10. 截屏悬浮软件_吹爆的软件,准确率太强了!
  11. 线性表——顺序表的应用
  12. 《电路分析导论(原书第12版)》一2.8 导体和绝缘体
  13. MongoTemplate 关于 insert 和 save 函数的区别
  14. 安装SVN及安装语言包
  15. 面试宝典之深度学习面试题(下)
  16. java怎么打hello,java hello word怎么打
  17. SpringBoot+vue项目实战(一)
  18. DNS劫持是什么意思?DNS被劫持怎么办?dns被劫持了怎么处理
  19. opj线性表Placing apples 题解
  20. hualinux 1.25:Web开发技术发展史

热门文章

  1. 使用伪类实现划掉字体
  2. apche的log4j.properties和log4j2.xml的配置和使用
  3. hadoop+Spark+hbase集群动态增加节点
  4. 真◉彻底解决 gcr、quay、DockerHub 镜像下载难题!
  5. 电子日历插件(阳历转阴历工具...)
  6. 一个字段,就可以判断是否关注公众号,你信吗
  7. SylixOS中断延迟队列
  8. Taprint: Secure Text Input for Commodity Smart Wristbands
  9. 小程序的横向二级顶部导航条,可以切换、拖动、二级定位在一级的下面,高度怎么办
  10. 如何做好性能压测(一) | 压测环境的设计和搭建