乘法密码技术:
属于替换密码技术的一种
乘法密码技术的加密变换: Ek(Ai)=Aj j=ik(mod n) ,gcd(k,n)=1
(1)0<k<n
(2)k与n互素,即要满足gcd(k, n)=1,否则不存在模逆元,不能正确解密
设明文消息为M,消息元素为m 元素下标为 i;
则密文消息为C,密文元素为c 元素下标为 j; c=i*k mod n;
乘法密码的密码空间大小是φ(n),φ(n)是欧拉函数。
当n为26字母,则与26互素的数是1、3、5、7、9、11、15、17、19、21、23、25,即φ(n)=12 因此乘法密码的密钥空间为12。
注意:k=1时 加密变换为恒等变换(即无变化)
乘法密码也称采样密码,因为密文字母表是将明文字母按照下标每隔k位取出一个字母排列而成。
例如对26个字母生成密码表(下标由0开始,0-25)
取k=9
明文字母 a b c d e f g h i j k l m n o p q r s t u v w x y z
数组下标 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
密文字母 a j s b k t c l u d m v e n w f o x g p y h q z i r
数组下标 0 9 18 1 10 19 2 11 20 3 12 21 4 13 22 5 14 23 6 15 24 7 16 25 8 17
正如上所述,从下标0开始, 明文a: 0X9%26=0 -->[0]=a 明文b: 1X9%26=9 -->[9]=j
其实即是通过公式算出密文密码表,其意义与明文表相一一对应。
乘法密码技术的解密变换: Dk(Aj)=Ai ,i=jX(mod n) X为k的逆元(最小正整数)
对于正整数 k和n,如果有kX≡1(mod m),那么把这个同余方程中X的最小正整数解叫做k模n的逆元。
一、欧拉定理(费马小定理)
欧拉定理:若a与m互质,那么有a^φ(m)≡1(mod m)
则a^-1 =a^(φ(m)-1) mod m
二、扩展的欧几里得算法
对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数,
必然存在整数对 x,y ,使得 gcd(a,b)=ax+by。
public static int ex_gcd(int a,int b){
if(b==0){
x=1;y=0;
return a;
}
int q=ex_gcd(b,a%b);
int t=x;x=y;y=t-a/b*y;
return q;
}
q即为a与b 的最大公约数,此处与原先算法相同
--------------------------------------------------------
由于本问题中k与n互素,gcd(k,n)=1 即上述q恒为1
public class ex_Eulid {
public static int x=0,y=0;
public static int ex_gcd(int a,int b){
if(b==0)
{
x=1;y=0;
return a;
}
int q=ex_gcd(b,a%b);
int t=x;x=y;y=t-a/b*y;
return q;
}
public static void main(String[] args) {
int k=9,n=26;
int a=k,b=n;
ex_gcd(a, b);
int out=(x+n)%n;
System.out.println(out);
}
}
上述所得out输出即为所需逆元
通过 Dk(Aj)=Ai ,i=jX(mod n) 将out代入X 即可恢复明文
import java.util.ArrayList;
import java.util.Scanner;
public class 乘法密码技术 {
public static int x=0,y=0;
public static ArrayList<Integer> SecretPlace=new ArrayList();
public static int gcd(int a,int b){
return b>0?gcd(b,a%b):a;
}
public static int ex_gcd(int a,int b){
if(b==0){
x=1;y=0;
return a;
}
int q=ex_gcd(b,a%b);
int t=x;x=y;y=t-a/b*y;
return q;
}
public static void CountSecretPlace(int n){
SecretPlace.add(1);
for(int i=2;i<n;i++){
if(gcd(i, n)==1)
SecretPlace.add(i);
}
}
public static void main(String[] args) {
int k;
Scanner scan=new Scanner(System.in);
System.out.println("第一行输入密码表总数n\n第二行输入各明文字符\n第三行输入待加密明文");
int n=scan.nextInt();
char CharArrays[]=new char[n];
CharArrays=scan.next().toCharArray();
scan.nextLine();
String normalStr=scan.nextLine();
CountSecretPlace(n);
System.out.println("密钥空间如下,您可选择其中一个值作为密钥");
System.out.println(SecretPlace);
k=scan.nextInt();
while(!SecretPlace.contains(k)){
System.out.println("只能选择密钥空间中的密钥值!请重新选择");
k=scan.nextInt();
}
ex_gcd(k, n);
int out=(x+n)%n;
System.out.println("您选择的密钥模逆元为:"+out);
String splitStrs[]=normalStr.split(" ");
ArrayList<Character> templist=new ArrayList<>();
System.out.println("加密后如下:");
for (int j = 0; j < splitStrs.length; j++) {
char normalChars[]=splitStrs[j].toCharArray();
for (int p = 0; p < normalChars.length; p++) {
int t=(normalChars[p]-'a')*k%n;
normalChars[p]=CharArrays[t];//加密
System.out.print(normalChars[p]);
normalChars[p]=CharArrays[t*out%n];//解密
templist.add(normalChars[p]);
}
System.out.print(" ");
templist.add(' ');
}
System.out.println("\n解密后如下:");
for(Character o:templist){
System.out.print(o);
}
}
}
运行结果如下:
第一行输入密码表总数n
第二行输入各密文字符
第三行输入待加密明文
26
abcdefghijklmnopqrstuvwxyz
a man liberal in his views
密钥空间如下,您可选择其中一个值作为密钥
[1, 3, 5, 7, 9, 11, 15, 17, 19, 21, 23, 25]
9
您选择的密钥模逆元为:3
加密后如下:
a ean vujkxav un lug hukqg
解密后如下:
a man liberal in his views
属于替换密码技术的一种
乘法密码技术的加密变换: Ek(Ai)=Aj j=ik(mod n) ,gcd(k,n)=1
(1)0<k<n
(2)k与n互素,即要满足gcd(k, n)=1,否则不存在模逆元,不能正确解密
设明文消息为M,消息元素为m 元素下标为 i;
则密文消息为C,密文元素为c 元素下标为 j; c=i*k mod n;
乘法密码的密码空间大小是φ(n),φ(n)是欧拉函数。
当n为26字母,则与26互素的数是1、3、5、7、9、11、15、17、19、21、23、25,即φ(n)=12 因此乘法密码的密钥空间为12。
注意:k=1时 加密变换为恒等变换(即无变化)
乘法密码也称采样密码,因为密文字母表是将明文字母按照下标每隔k位取出一个字母排列而成。
例如对26个字母生成密码表(下标由0开始,0-25)
取k=9
明文字母 a b c d e f g h i j k l m n o p q r s t u v w x y z
数组下标 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
密文字母 a j s b k t c l u d m v e n w f o x g p y h q z i r
数组下标 0 9 18 1 10 19 2 11 20 3 12 21 4 13 22 5 14 23 6 15 24 7 16 25 8 17
正如上所述,从下标0开始, 明文a: 0X9%26=0 -->[0]=a 明文b: 1X9%26=9 -->[9]=j
其实即是通过公式算出密文密码表,其意义与明文表相一一对应。
乘法密码技术的解密变换: Dk(Aj)=Ai ,i=jX(mod n) X为k的逆元(最小正整数)
对于正整数 k和n,如果有kX≡1(mod m),那么把这个同余方程中X的最小正整数解叫做k模n的逆元。
由于k的取值是从φ(n) 密码空间中获得,则必定k<n
一、欧拉定理(费马小定理)
欧拉定理:若a与m互质,那么有a^φ(m)≡1(mod m)
则a^-1 =a^(φ(m)-1) mod m
二、扩展的欧几里得算法
对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数,
必然存在整数对 x,y ,使得 gcd(a,b)=ax+by。
public static int ex_gcd(int a,int b){
if(b==0){
x=1;y=0;
return a;
}
int q=ex_gcd(b,a%b);
int t=x;x=y;y=t-a/b*y;
return q;
}
q即为a与b 的最大公约数,此处与原先算法相同
--------------------------------------------------------
由于本问题中k与n互素,gcd(k,n)=1 即上述q恒为1
对于可利用(X+n)%n 来获得正整数逆元。
public class ex_Eulid {
public static int x=0,y=0;
public static int ex_gcd(int a,int b){
if(b==0)
{
x=1;y=0;
return a;
}
int q=ex_gcd(b,a%b);
int t=x;x=y;y=t-a/b*y;
return q;
}
public static void main(String[] args) {
int k=9,n=26;
int a=k,b=n;
ex_gcd(a, b);
int out=(x+n)%n;
System.out.println(out);
}
}
上述所得out输出即为所需逆元
通过 Dk(Aj)=Ai ,i=jX(mod n) 将out代入X 即可恢复明文
import java.util.ArrayList;
import java.util.Scanner;
public class 乘法密码技术 {
public static int x=0,y=0;
public static ArrayList<Integer> SecretPlace=new ArrayList();
public static int gcd(int a,int b){
return b>0?gcd(b,a%b):a;
}
public static int ex_gcd(int a,int b){
if(b==0){
x=1;y=0;
return a;
}
int q=ex_gcd(b,a%b);
int t=x;x=y;y=t-a/b*y;
return q;
}
public static void CountSecretPlace(int n){
SecretPlace.add(1);
for(int i=2;i<n;i++){
if(gcd(i, n)==1)
SecretPlace.add(i);
}
}
public static void main(String[] args) {
int k;
Scanner scan=new Scanner(System.in);
System.out.println("第一行输入密码表总数n\n第二行输入各明文字符\n第三行输入待加密明文");
int n=scan.nextInt();
char CharArrays[]=new char[n];
CharArrays=scan.next().toCharArray();
scan.nextLine();
String normalStr=scan.nextLine();
CountSecretPlace(n);
System.out.println("密钥空间如下,您可选择其中一个值作为密钥");
System.out.println(SecretPlace);
k=scan.nextInt();
while(!SecretPlace.contains(k)){
System.out.println("只能选择密钥空间中的密钥值!请重新选择");
k=scan.nextInt();
}
ex_gcd(k, n);
int out=(x+n)%n;
System.out.println("您选择的密钥模逆元为:"+out);
String splitStrs[]=normalStr.split(" ");
ArrayList<Character> templist=new ArrayList<>();
System.out.println("加密后如下:");
for (int j = 0; j < splitStrs.length; j++) {
char normalChars[]=splitStrs[j].toCharArray();
for (int p = 0; p < normalChars.length; p++) {
int t=(normalChars[p]-'a')*k%n;
normalChars[p]=CharArrays[t];//加密
System.out.print(normalChars[p]);
normalChars[p]=CharArrays[t*out%n];//解密
templist.add(normalChars[p]);
}
System.out.print(" ");
templist.add(' ');
}
System.out.println("\n解密后如下:");
for(Character o:templist){
System.out.print(o);
}
}
}
运行结果如下:
第一行输入密码表总数n
第二行输入各密文字符
第三行输入待加密明文
26
abcdefghijklmnopqrstuvwxyz
a man liberal in his views
密钥空间如下,您可选择其中一个值作为密钥
[1, 3, 5, 7, 9, 11, 15, 17, 19, 21, 23, 25]
9
您选择的密钥模逆元为:3
加密后如下:
a ean vujkxav un lug hukqg
解密后如下:
a man liberal in his views