基于 CS 模式的sha256加密算法,包括代码、答辩文件、实验报告

基于 CS 模式或者 BS 模式 Hash 算法 软件包括客户端和服务器端,客户端实现文件 Hash 值计算,服务器端接收 的文件和 Hash 值,进行文件完整性验证。软件具体功能如下:
(1) 客户端文件 Hash 的计算 a)输入任意文件格式的文件
b)采用 Hash 算法计算 Hash 值,并十六进制显示 hash 值,然后把文件和 hash 值给服务器端
(2) 服务器端验证文件的完整性 a)接收端客户端文件和 Hash 值,然后分离得到文件和收到 Hash 值,然后 采用跟客户端一样 Hash 函数计算文件 Hash 值,计算 Hash 值与收到 Hash 比 较,若一致,则文件完整性认证通过,若不一致,则文件完整性验证不通过;
其它要求:
(1)用函数实现 Hash 算法
(2)可选择 C、C++、Java、Python 等任意一种编程语言实现。

在这里插入图片描述

核心代码:

//SHA-256 是一种密码学安全哈希函数,它能将不定长度的消息輸
// 入(input)進行加密,生成一个固定长度的哈希值(digest)。
#include <iostream>
#include <cstring>
#include <iomanip>
#include <sstream>
// 定义了一个右旋转操作 rightRotate,用于将二进制位向右旋转 n 位;
uint32_t rightRotate(uint32_t x, uint32_t n) {
    return (x >> n) | (x << (32 - n));
}

//定义了一个常量数组 k,存储了 64 个常数,用于后续哈希计算;
const uint32_t k[64] = {
        0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
        0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
        0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
        0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
        0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
        0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
        0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
        0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
        0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
        0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
        0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
        0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
        0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
        0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
        0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
        0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};

// 定义了一个求 x 的 n 次方的函数 pow,用于一些哈希计算中;
uint32_t pow(uint32_t x, uint32_t n) {
    uint32_t result = 1;
    for (int i = 0; i < n; i++) {
        result *= x;
    }
    return result;
}

// 定义了一个取 w 的第 n 个 32 位字的函数 getWord,用于一些哈希计算中;
uint32_t getWord(uint32_t w, uint32_t n) {
    return (w >> (24 - n * 8)) & 0xff;
}

// 定义了 sha256 函数,实现 SHA-256 哈希计算,并将计算结果以字符串形式返回。
std::string sha256(const unsigned char* data, size_t length) {
    //(1) 初始化 8 个 32 位的数(H0 ~ H7),用于后续哈希计算;
    uint32_t h0 = 0x6a09e667; //存储哈希值H0
    uint32_t h1 = 0xbb67ae85; //存储哈希值H1
    uint32_t h2 = 0x3c6ef372; //存储哈希值H2
    uint32_t h3 = 0xa54ff53a; //存储哈希值H3
    uint32_t h4 = 0x510e527f; //存储哈希值H4
    uint32_t h5 = 0x9b05688c; //存储哈希值H5
    uint32_t h6 = 0x1f83d9ab; //存储哈希值H6
    uint32_t h7 = 0x5be0cd19; //存储哈希值H7

    //(2) 对输入的数据进行补位,使其长度满足 512 位的倍数,并且
    // 在补位后的数据尾部添加一个 64 位的长度值,表示原始消息的长度(单位为位,64 位二进制数);
    uint64_t bitLength = length * 8; //记录输入数据的长度
    uint64_t paddingLength = (512 - (bitLength + 64) % 512) % 512; //计算需要补充的字节数
    uint64_t newLength = length + paddingLength / 8 + 8; //计算补充后的总字节数,加上 8 是因为后面要在末尾加上一个长度为 64 位的值
    uint8_t* newData = new uint8_t[newLength]; //创建一个新内存进行哈希计算
    memset(newData, 0, newLength); //将新内存全部填充为 0
    memcpy(newData, data, length); //将输入的数据复制到新内存中
    newData[length] = 0x80; //在复制完数据后,末尾填充 1

    for (int i = 0; i < 8; i++) {
        //将长度为 64 位的消息长度写入末尾
        newData[newLength - 8 + i] = (bitLength >> (56 - i * 8)) & 0xff;
    }
    //(3) 对于每个 512 位的消息块,进行哈希计算,最终得到的哈希值就是 sha256 算法的结果。

    for (int i = 0; i < newLength; i += 64) {
        //每次处理 512 位数据(64 个字),分为 16 组,每组 4 个字节(一个 uint32_t)
        uint32_t w[64];
        for (int j = 0; j < 16; j++) {
            // 将 4 个字节组成一个 uint32_t
            w[j] = (newData[i + j * 4] << 24) | (newData[i + j * 4 + 1] << 16) | (newData[i + j * 4 + 2] << 8) | newData[i + j * 4 + 3];
        }
        for (int j = 16; j < 64; j++) {
            // 对 w[0] 到 w[15] 进行扩展
            uint32_t s0 = rightRotate(w[j - 15], 7) ^ rightRotate(w[j - 15], 18) ^ (w[j - 15] >> 3);
            uint32_t s1 = rightRotate(w[j - 2], 17) ^ rightRotate(w[j - 2], 19) ^ (w[j - 2] >> 10);
            w[j] = w[j - 16] + s0 + w[j - 7] + s1;
        }
        uint32_t a = h0;
        uint32_t b = h1;
        uint32_t c = h2;
        uint32_t d = h3;
        uint32_t e = h4;
        uint32_t f = h5;
        uint32_t g = h6;
        uint32_t h = h7;

        //逐步处理每个字
        for (int j = 0; j < 64; j++) {
            uint32_t S1 = rightRotate(e, 6) ^ rightRotate(e, 11) ^ rightRotate(e, 25);
            uint32_t ch = (e & f) ^ ((~e) & g);
            uint32_t temp1 = h + S1 + ch + k[j] + w[j];
            uint32_t S0 = rightRotate(a, 2) ^ rightRotate(a, 13) ^ rightRotate(a, 22);
            uint32_t maj = (a & b) ^ (a & c) ^ (b & c);
            uint32_t temp2 = S0 + maj;
            h = g;
            g = f;
            f = e;
            e = d + temp1;
            d = c;
            c = b;
            b = a;
            a = temp1 + temp2;
        }
        h0 += a;
        h1 += b;
        h2 += c;
        h3 += d;
        h4 += e;
        h5 += f;
        h6 += g;
        h7 += h;
    }
    delete[] newData; //释放内存
    //将每个哈希值以 16 进制的形式表示,并拼接成一个字符串
    std::stringstream ss;
    ss << std::hex << std::setfill('0') << std::setw(8) << h0
       << std::setw(8) << h1 << std::setw(8) << h2 << std::setw(8) << h3
       << std::setw(8) << h4 << std::setw(8) << h5 << std::setw(8) << h6 << std::setw(8) << h7;
    std::cout<<"生成的sha256哈希值是:"<<ss.str()<<std::endl;
    return ss.str(); //返回哈希值
}



完整代码实现文件已经打包放在压缩包中,需要的自取:
链接: https://pan.baidu.com/s/1oo0I5elf3apYs9yUzWyhmg?pwd=mvuy 提取码: mvuy

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,以下是Java实现的基于cs模式的sm4算法加解密软件实现: 服务端代码: ```java import cn.com.sgcc.crypto.SM4; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.nio.charset.StandardCharsets; public class SM4Server { private static final int PORT = 8888; private static final String KEY = "1234567890abcdef"; public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(PORT); System.out.println("Server started, waiting for client connection..."); while (true) { Socket socket = serverSocket.accept(); System.out.println("Client connected: " + socket.getInetAddress().getHostAddress()); new Thread(() -> { try { DataInputStream dis = new DataInputStream(socket.getInputStream()); DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); while (true) { int type = dis.readInt(); if (type == 0) { // 加密 int length = dis.readInt(); byte[] data = new byte[length]; dis.readFully(data); byte[] encryptedData = SM4.encrypt_ECB(data, KEY.getBytes(StandardCharsets.UTF_8)); dos.writeInt(encryptedData.length); dos.write(encryptedData); dos.flush(); } else if (type == 1) { // 解密 int length = dis.readInt(); byte[] data = new byte[length]; dis.readFully(data); byte[] decryptedData = SM4.decrypt_ECB(data, KEY.getBytes(StandardCharsets.UTF_8)); dos.writeInt(decryptedData.length); dos.write(decryptedData); dos.flush(); } else { break; } } dis.close(); dos.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } }).start(); } } } ``` 客户端代码: ```java import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; import java.nio.charset.StandardCharsets; public class SM4Client { private static final String HOST = "127.0.0.1"; private static final int PORT = 8888; public static void main(String[] args) throws IOException { Socket socket = new Socket(HOST, PORT); System.out.println("Connected to server: " + socket.getInetAddress().getHostAddress()); DataInputStream dis = new DataInputStream(socket.getInputStream()); DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); String input = "这是一段测试字符串。"; byte[] inputData = input.getBytes(StandardCharsets.UTF_8); // 加密 dos.writeInt(0); // 指定为加密操作 dos.writeInt(inputData.length); dos.write(inputData); dos.flush(); int encryptedLength = dis.readInt(); byte[] encryptedData = new byte[encryptedLength]; dis.readFully(encryptedData); String encryptedText = new String(encryptedData, StandardCharsets.UTF_8); System.out.println("Encrypted text: " + encryptedText); // 解密 dos.writeInt(1); // 指定为解密操作 dos.writeInt(encryptedLength); dos.write(encryptedData); dos.flush(); int decryptedLength = dis.readInt(); byte[] decryptedData = new byte[decryptedLength]; dis.readFully(decryptedData); String decryptedText = new String(decryptedData, StandardCharsets.UTF_8); System.out.println("Decrypted text: " + decryptedText); dis.close(); dos.close(); socket.close(); } } ``` 需要注意的是,在这里我们使用了SM4算法的ECB模式进行加解密,因此需要保证每次加密的明文长度和密钥长度是一致的。在实际应用中,可以考虑使用SM4算法的CBC或CTR模式,以提高加密的安全性。同时,在实际应用中还需要考虑对数据进行完整性校验,防止数据被篡改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

就是木子呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值