Skip to content
Bryce Ai edited this page Jun 21, 2023 · 3 revisions

Welcome to the FileEncryptionAndDecryptionProgramDemo wiki!


文件加密和解密功能的核心代码:

int i = 0;
while(!fileStrem.atEnd())
{
    uint bufferSize = 1;
    char buffer[1];
    //从文件流中读取缓存区大小的字节到buffer中

    qint64 bytesRead = fileStrem.readRawData(buffer, bufferSize);

    //检查读取是否成功
    if (bytesRead == -1)
    {
        //错误处理
        break;
    }
    buffer[0] ^= passwordKey[i++ % pwdlen];
    //从buffer中写入读取到的字节到目标文件流
    file_edStream.writeRawData(buffer, bytesRead);
}

上述代码通过读取文件流的方式,逐个字节地将文件内容与密码密钥进行异或操作,实现了文件的加密功能。同时,通过更新进度条的方式,提供了加密过程的可视化。

RSA加密解密核心代码

进制转换

int PasswordGenerator::BianaryTransform(int num, int bin_num[])
{
    int i = 0,  mod = 0;
    //转换为二进制,逆向暂存temp[]数组中
    while(num != 0)
    {
        mod = num%2;
        bin_num[i] = mod;
        num = num/2;
        i++;
    }
    //返回二进制数的位数
    return i;
}

这段代码实现的是将一个十进制整数转换为二进制数并保存到一个数组中,同时返回二进制数的位数。具体的运行过程如下:

  1. 接收一个十进制整数 num 和一个用于保存二进制数的数组 bin_num。
  2. 定义两个变量 i 和 mod。变量 i 用于记录二进制数的位数,变量 mod 用于保存每次对 2 取余运算的结果。
  3. 进行十进制转二进制的操作,直到 num 变为0为止。具体流程如下:
  • 将 num 对 2 取余得到 mod。
  • 将 mod 存储到数组 bin_num 的第 i 个位置。
  • 将 num 除以 2,得到一个新的 num 值,用于下一次的取余操作。
  • i 自增 1,表示保存了一个二进制位。
  1. 返回变量 i,即为二进制数的位数。

反复平方求幂

long long PasswordGenerator::Modular_Exonentiation(long long a, int b, int n)
{
    int c = 0, bin_num[1000];
    long long d = 1;
    int k = BianaryTransform(b, bin_num)-1;

    for(int i = k; i >= 0; i--)
    {
        c = 2*c;
        d = (d*d)%n;
        if(bin_num[i] == 1)
        {
            c = c + 1;
            d = (d*a)%n;
        }
    }
    return d;
}

这段代码实现的是快速幂算法,用于计算 a^b mod n 的值。具体的运行过程如下:

  1. 接收三个输入参数 a、b 和 n,其中 a 为底数,b 为指数,n 为模数。
  2. 定义变量 c 和 d。变量 c 用于记录二进制数的每一位,变量 d 用于保存每次计算的结果。
  3. 调用 BianaryTransform() 函数将 b 转换成二进制数,并得到二进制数的位数 k。同时定义一个数组 bin_num,用于保存二进制数中每一位的取值。
  4. 进行快速幂算法的计算。具体流程如下:
  • 从二进制数的最高位开始循环,一直到最低位。
  • 对于每一位,将 c 乘以 2,并将 d 的平方对 n 取余。这个过程相当于对二进制数中的每一位进行左移操作,同时在 d 上进行平方。
  • 如果这一位为 1,则将 c 加 1。同时将 d 与 a 相乘,再对 n 取余。这个过程相当于在当前的基础上乘以一个 a。
  1. 返回变量 d,即为最终计算结果 a^b mod n 的值。

生成1000以内素数

int PasswordGenerator::ProducePrimeNumber(int prime[])
{
    int c = 0, vis[1001];
    memset(vis, 0, sizeof(vis));
    for(int i = 2; i <= 1000; i++)if(!vis[i])
        {
            prime[c++] = i;
            for(int j = i*i; j <= 1000; j+=i)
                vis[j] = 1;
        }

    return c;
}

这段代码实现的是生成小于等于1000的所有素数,并将这些素数保存到一个数组中。具体的运行过程如下:

  1. 定义数组 prime 用于保存素数,数组 vis 用于判断一个数是否为素数,初始值为0。
  2. 对于每个从 2 到 1000 的数,如果 vis 数组中对应的值为0,则说明该数为素数。将该素数存储到数组 prime 的最后一个位置,并将素数计数器 c 加1。同时,将该素数的倍数在 vis 数组中标记为1,表示不是素数。
  3. 返回素数的数量 c。

欧几里得扩展算法

int PasswordGenerator::Exgcd(int m,int n,int &x)
{
    int x1,y1,x0,y0, y;
    x0=1; y0=0;
    x1=0; y1=1;
    x=0; y=1;
    int r=m%n;
    int q=(m-r)/n;
    while(r)
    {
        x=x0-q*x1; y=y0-q*y1;
        x0=x1; y0=y1;
        x1=x; y1=y;
        m=n; n=r; r=m%n;
        q=(m-r)/n;
    }
    return n;
}

这段代码实现的是求解 m 和 n 的最大公约数和一组贝祖等式中的解 x,即 gcd(m,n) = mx + ny 其中 m 和 n 是两个正整数,x 是函数参数,y 是函数返回值。 函数 Exgcd 中定义了变量 x1、y1、x0、y0 和 y,分别表示计算过程中的系数。在函数刚开始时,初始化 x0=1,y0=0,x1=0,y1=1,x=0,y=1,r=m%n,q=(m-r)/n,其中 q 是商,r 是模数。然后进入 while 循环,直到 r 的值为 0 时结束循环。 在循环中,先计算出新的 x 和 y 的值,然后更新 x0、y0、x1、y1、m、n、r、q 的值。其中,x 和 y 的计算用到了扩展欧几里得算法的关键步骤,根据贝祖等式可知:

Mx_1 + ny_1= r Mx_0+ ny_0= n Mx + ny= mx_0+ ny_0- q(mx_1+ ny_1 ) = mx_0+ ny_0- q(r - mx_1- ny_1 ) = n_x+ n_y

其中,n_x = x0 – q * x1,n_y = y0 – q * y1。X,y 的计算可以通过不断更新 n_x 和 n_y 得到。 最后返回 n 的值,即为 m 和 n 的最大公约数。这个算法实现了扩展欧几里得算法,时间复杂度为 O(log n)。

RSA初始化

void PasswordGenerator::RSA_Initialize()
{
    //取出1000内素数保存在prime[]数组中
    int prime[5000];
    int count_Prime = ProducePrimeNumber(prime);
    //随机取两个素数p,q
    srand((unsigned)time(NULL));
    int ranNum1 = rand()%count_Prime;
    int ranNum2 = rand()%count_Prime;
    int p = prime[ranNum1], q = prime[ranNum2];
    n = p*q;
    int On = (p-1)*(q-1);
    //用欧几里德扩展算法求e,d
    for(int j = 3; j < On; j+=1331)
    {
        int gcd = Exgcd(j, On, d);
        if( gcd == 1 && d > 0)
        {
            e = j;
            break;
        }
    }
    this->ui->lineEdit->setText(QString(QString::number(n)));
    this->ui->lineEdit_2->setText(QString(QString::number(e)));
    this->ui->lineEdit_3->setText(QString(QString::number(d)));
}

这段代码实现的是 RSA 密码算法的初始化过程,在该过程中通过随机取两个素数 p 和 q 来生成一个公钥和一个私钥。具体的运行过程如下:

  1. 调用 ProducePrimeNumber() 函数获取小于等于1000的所有素数,并将这些素数保存在 prime[] 数组中。
  2. 通过 rand() 函数随机取两个数 ranNum1 和 ranNum2,用这两个数对应的素数 p 和 q 生成一个 RSA 密码算法中使用的模数 n,即 n=p*q。
  3. 计算欧拉函数 On=(p-1)×(q-1)。
  4. 在循环中对 e 进行枚举,找到一个与 On 互质的数。具体流程如下:
  • 从 3 开始,以 1331 为步长枚举每一个奇数,直到找到一个与 On 互质的数 e。
  • 对当前枚举的数 e 进行扩展欧几里得算法,计算得到 e 对应的 d 值,并检查是否满足 gcd(e,On)=1,且 d>0。
  1. 将得到的 n、e、d 三个值分别保存到 QLineEdit 对象中以供后面使用。

RSA加密

void PasswordGenerator::RSA_Encrypt()
{
    int i = 0;
    for(i = 0; i < 100; i++)
        Ciphertext[i] = Modular_Exonentiation(Plaintext[i], e, n);

    QString codeStt = "";
    this->ui->textEdit->append(QString("加密后密文:"));
    for(i = 0; i < 100; i++)
    {
        cout<<Ciphertext[i]<<" ";
        codeStt += QString::number(Ciphertext[i]);
        codeStt += QString(' ');

    }
        this->ui->textEdit->append(codeStt);
       encryptionCompleted(codeStt);
}

这段代码实现的是 RSA 密码算法中的加密过程,将明文加密为密文。具体的运行过程如下:

  1. 定义一个循环变量 i,并使用 Modular_Exponentiation() 函数对明文中的每一个字符进行加密,将加密结果保存到 Ciphertext 数组中。
  2. 将加密后的密文 Ciphertext 数组转换成字符串形式,并将其添加到 QTextEdit 对象中展示。同时触发信号 encryptionCompleted(),将加密后的密文传递给槽函数进行处理。

RSA解密

void PasswordGenerator::RSA_Decrypt()
{
    int i = 0;
    for(i = 0; i < 100; i++)
        Ciphertext[i] = Modular_Exonentiation(Ciphertext[i], d, n);
    QString codeStt = "";
    //cout<<"Use private key (d, n) to decrypt:"<<'\n';
    this->ui->textEdit->append(QString("解密后明文:"));
    for(i = 0; i < 100; i++)
    {
        cout<<Ciphertext[i]<<" ";
        codeStt += QString::number(Ciphertext[i]);
        codeStt += QString(' ');

    }
    this->ui->textEdit->append(codeStt);
}

这段代码实现的是 RSA 密码算法中的解密过程,将密文解密为明文。具体的运行过程如下:

  1. 定义一个循环变量 i,并使用 Modular_Exponentiation() 函数对密文中的每一个字符进行解密,将解密结果保存到 Ciphertext 数组中。

  2. 将解密后的明文 Ciphertext 数组转换成字符串形式,并将其添加到 QTextEdit 对象中展示。

RSA算法初始化

void PasswordGenerator::Initialize()
{
    int i;
    srand((unsigned)time(NULL));
    for(i = 0; i < 100; i++)
        Plaintext[i] = rand()%1000;
    this->ui->textEdit->append(QString("明文密码:"));
    QString codeStt = "";
    //cout<<"Generate 100 random numbers:"<<'\n';
    for(i = 0; i < 100; i++)
    {
        cout<<Plaintext[i]<<" ";
        codeStt += QString::number(Plaintext[i]);
        codeStt += QString(' ');

    }
        //cout<<Plaintext[i]<<" ";
    this->ui->textEdit->append(codeStt);
}

这段代码实现的是 RSA 密码算法中明文的初始化过程,生成100个随机数作为明文。具体的运行过程如下:

  1. 定义一个循环变量 i,并使用 srand() 函数进行初始化,设置种子为当前时间戳。
  2. 在循环中使用 rand() 函数生成100个随机数,并将这些随机数保存在 Plaintext 数组中。
  3. 将生成的明文 Plaintext 数组转换成字符串形式,并将其添加到 QTextEdit 对象中展示。