S-DES加密算法介绍与实现

为了更好地理解DES算法,美国圣克拉拉大学的Edward Schaefer教授于1996年开发了Simplfied DES方案,简称S-DES方案。它是一个供教学而非安全使用的加密算法,它与DES的特性和结构类似,但参数小,明文分组为8位,主密钥分组为10位,采用两轮选代。

S-DES的加密原理图
S-DES的加密原理图如上图所示
S-DES的具体实现步骤:

  1. 初始置换IP:将8位的明文按照置换顺序分为左4位 L 0 L_0 L0和右4位 R 0 R_{0} R0
  2. 第1轮运算, R 0 R_0 R0一方面直接输出作为下一轮的 L 1 L_1 L1,另一方面作为f函数的输入与8位的子密钥 K 1 K_1 K1参与函数运算,运算结果与 L 0 L_0 L0异或,结果作为下一轮的 R 1 R_1 R1
  3. 第2轮运算, R 1 R_1 R1一方面直接输出作为下一轮的 R 2 R_2 R2,另一方面作为f函数的输入与8位子密钥 K 2 K_2 K2参与函数运算,运算结构与 L 1 L_1 L1异或,结果作为下一轮的 L 2 L_2 L2
  4. 逆置换 I P − 1 IP^{-1} IP1

S-DES的子密码生成过程
S-DES子密钥生成过程的步骤:

  1. 主密钥K进行P10置换(35274,10,1986)
  2. 分成左5位和右5位,再进行 L S − 1 LS-1 LS1操作(左循环1位),其结果一方面作为下一轮的初始值,一方面进行P8置换(637485,10,9),得到 K 1 K_1 K1
  3. 将上一轮结果分布左循环2位,经过P8置换,得到 K 2 K_2 K2

S-DES的f函数结构
S-DES的f函数结构如上图所示
S-DES的f函数结构的具体实现步骤:

  1. E/P扩展及置换: 将4位扩展为8位
  2. 扩展后的8位与密钥 K 1 K_1 K1 K 2 K_2 K2异或,输出8位
  3. 左边4位作为 S 1 S_1 S1,输入,右边4位作为 S 2 S_2 S2输入
  4. S 1 S_1 S1 S 2 S_2 S2中,分别将第1位与第4位结合,形成2位代表S盒的行号,分别将第2位与第3位结合,形成2位代表S盒的列号,从而得到S盒的输出。S-DES的S盒如下表所示
  5. 进行 P 4 P4 P4置换,得到 f f f函数的输出

S-DES的S盒

$S_1$$00$$01$$10$$11$$S_2$$00$$01$$10$$11$
$00$01001110$00$00011011
$01$11100100$01$10000111
$10$00100111$10$11100100
$11$11010010$11$10010011
S-DES解密的步骤:
  1. IP置换(26314857)
  2. 如图一逆过程从 L 2 L_2 L2 R 2 R_2 R2开始倒着来
  3. I P − 1 IP^{-1} IP1置换(41357286)

如设主密钥 K K K=1010000010,用S-DES加密明文字母 C C C

  1. 先求得 K 1 K_1 K1 K 2 K_2 K2,主密钥经过P10置换的到:1000001100
  2. L S − 1 LS-1 LS1操作:0000111000
  3. P8置换产生 K 1 K_1 K1:10100100
  4. L S − 2 LS-2 LS2操作:0010000011
  5. P8置换产生 K 2 K_2 K2:01000011
  6. 字母 C C C的ASCII码为67,对应二进制位01000011
  7. IP置换: L 0 L_0 L0=1000, R 0 R_0 R0=0101
  8. 第1轮: f ( R 0 , K 1 ) f(R_0,K_1) f(R0,K1)=1000, L 0 ⨁ f = 1000 ⨁ 1000 = 0000 L_0\bigoplus f=1000\bigoplus 1000=0000 L0f=10001000=0000
  9. L 1 = R 0 = 0101 L_1=R_0=0101 L1=R0=0101, R 1 R_1 R1=0000
  10. 第二轮: f ( R 1 , K 2 ) f(R_1,K_2) f(R1,K2)=1001, L 1 ⨁ f = 0101 ⨁ 1001 = 1100 L_1\bigoplus f=0101\bigoplus 1001=1100 L1f=01011001=1100
  11. L 2 L_2 L2=1100, R 2 = R 1 = 0000 R_2=R_1=0000 R2=R1=0000
  12. I P − 1 IP^{-1} IP1置换:01000100(ASCII码为68,对应字母D)

所以我们可以将其程序化

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
int S1[4][4][2]={{{0,1},{0,0},{1,1},{1,0}},
                 {{1,1},{1,0},{0,1},{0,0}},
                 {{0,0},{1,0},{0,1},{1,1}},
                 {{1,1},{0,1},{0,0},{1,0}}};
int S2[4][4][2]={{{0,0},{0,1},{1,0},{1,1}},
                 {{1,0},{0,0},{0,1},{1,1}},
                 {{1,1},{1,0},{0,1},{0,0}},
                 {{1,0},{0,1},{0,0},{1,1}}};
void createkey(int k[11],int k1[9],int k2[9])
{
    int temp[11];
    temp[1]=k[3],temp[2]=k[5],temp[3]=k[2],temp[4]=k[7],temp[5]=k[4],temp[6]=k[10],temp[7]=k[1],temp[8]=k[9],temp[9]=k[8],temp[10]=k[6];
    int l[6],r[6];
    for(int i=1;i<=5;i++)
        l[i]=temp[i],r[i]=temp[i+5];
    int x1,x2,x3,x4;
    x1=l[1],x2=r[1];
    for(int i=2;i<=5;i++)
        l[i-1]=l[i],r[i-1]=r[i];
    l[5]=x1;
    r[5]=x2;
    for(int i=1;i<=5;i++)
        temp[i]=l[i],temp[i+5]=r[i];
    k1[1]=temp[6],k1[2]=temp[3],k1[3]=temp[7],k1[4]=temp[4],k1[5]=temp[8],k1[6]=temp[5],k1[7]=temp[10],k1[8]=temp[9];
    x1=l[1],x2=l[2],x3=r[1],x4=r[2];
    for(int i=2;i<=5;i++)
        l[i-2]=l[i],r[i-2]=r[i];
    l[4]=x1,l[5]=x2;
    r[4]=x3,r[5]=x4;
    for(int i=1;i<=5;i++)
        temp[i]=l[i],temp[i+5]=r[i];
    k2[1]=temp[6],k2[2]=temp[3],k2[3]=temp[7],k2[4]=temp[4],k2[5]=temp[8],k2[6]=temp[5],k2[7]=temp[10],k2[8]=temp[9];
}
void f(int R[],int K[])
{
    int temp[9];
    temp[1]=R[4],temp[2]=R[1],temp[3]=R[2],temp[4]=R[3],temp[5]=R[2],temp[6]=R[3],temp[7]=R[4],temp[8]=R[1];
    for(int i=1;i<=8;i++)
        temp[i]=temp[i]^K[i];
    int s1[5],s2[5];
    for(int i=1;i<=4;i++)
        s1[i]=temp[i],s2[i]=temp[i+4];
    int x1=S1[s1[1]*2+s1[4]][s1[2]*2+s1[3]][0],x2=S1[s1[1]*2+s1[4]][s1[2]*2+s1[3]][1];
    int x3=S2[s2[1]*2+s2[4]][s2[2]*2+s2[3]][0],x4=S2[s2[1]*2+s2[4]][s2[2]*2+s2[3]][1];
    R[1]=x2,R[2]=x4,R[3]=x3,R[4]=x1;
}
void Encode(int x,int k1[],int k2[])
{
    int ming[9];
    for(int i=8;i>=1;i--)
    {
        ming[i]=x%2;
        x/=2;
    }
    int temp[9];
    temp[1]=ming[2],temp[2]=ming[6],temp[3]=ming[3],temp[4]=ming[1],temp[5]=ming[4],temp[6]=ming[8],temp[7]=ming[5],temp[8]=ming[7];
    int L0[5],R0[5],L1[5],R1[5],L2[5],R2[5];
    for(int i=1;i<=4;i++)
        L0[i]=temp[i],R0[i]=temp[i+4];
    memcpy(L1,R0,sizeof(L1));
    f(R0,k1);
    for(int i=1;i<=4;i++)
        R1[i]=L0[i]^R0[i];
    memcpy(R2,R1,sizeof(R2));
    f(R1,k2);
    for(int i=1;i<=4;i++)
        L2[i]=L1[i]^R1[i];
    temp[1]=L2[4],temp[2]=L2[1],temp[3]=L2[3],temp[4]=R2[1],temp[5]=R2[3],temp[6]=L2[2],temp[7]=R2[4],temp[8]=R2[2];
    printf("加密后二进制为:");
    int ans=0;
    for(int i=1;i<=8;i++)
        {
            ans+=temp[i]*(1<<(8-i));
            printf("%d",temp[i]);
        }
    printf("\n");
    printf("加密后对应字母为:%c\n",ans);
}
void Decode(int x,int k1[],int k2[])
{
    int ming[9];
    for(int i=8;i>=1;i--)
    {
        ming[i]=x%2;
        x/=2;
    }
    int temp[9];
    temp[1]=ming[2],temp[2]=ming[6],temp[3]=ming[3],temp[4]=ming[1],temp[5]=ming[4],temp[6]=ming[8],temp[7]=ming[5],temp[8]=ming[7];
    int L0[5],R0[5],L1[5],R1[5],L2[5],R2[5];
    for(int i=1;i<=4;i++)
        L2[i]=temp[i],R2[i]=temp[i+4];
    memcpy(R1,R2,sizeof(R1));
    f(R2,k2);
    for(int i=1;i<=4;i++)
        L1[i]=L2[i]^R2[i];
    memcpy(R0,L1,sizeof(R0));
    f(L1,k1);
    for(int i=1;i<=4;i++)
        L0[i]=R1[i]^L1[i];
    temp[1]=L0[4],temp[2]=L0[1],temp[3]=L0[3],temp[4]=R0[1],temp[5]=R0[3],temp[6]=L0[2],temp[7]=R0[4],temp[8]=R0[2];
    printf("解密后二进制为:");
    int ans=0;
    for(int i=1;i<=8;i++)
        {
            ans+=temp[i]*(1<<(8-i));
            printf("%d",temp[i]);
        }
    printf("\n");
    printf("解密后对应字母为:%c\n",ans);
}
int main()
{
    int k[11],k1[9],k2[9];
    printf("请输入主密钥K:");
    for(int i=1;i<=10;i++)
        scanf("%1d",&k[i]);
    createkey(k,k1,k2);
    char ming[2];
    printf("请输入明文:");
    scanf("%s",ming);
    Encode(ming[0],k1,k2);
    printf("请输入密文:");
    char mi[2];
    scanf("%s",mi);
    Decode(mi[0],k1,k2);
    return 0;
}



评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值