求一字符串加密算法(想说用“异或”的请免开尊口)

时间:2023-01-11 14:15:20
求一字符串加密算法(想说用“异或”的请免开尊口)
假设有一个字符串"ABCDEFG",想对其中的每一个字符进行加密。
加密结果要和原串的长度相同,加密出的结果不能有乱码或不可显示的字符。
并且可以解密还原成原串。
就是这样了,可以骗骗老板就可以了。
兄弟帮忙。

6 个解决方案

#1


转,矩阵加密法,用的VB的语法,但你一定能看懂。

简易的矩阵加密编码法(cipher) 
当储存一项机密的资料(譬如:密码)于档案中或是 Windows 的系统登录区(registry)中,通常不希望被别人直接看到资料内容,于是就必须对该资料作加密编码的处理后再储存之,欲取用时唯有知道加密编码算法的人才能将编码过的资料译码成原始资料。已知最早的加密编码法都是使用简单的代换法,也就是所谓的移位密码(shift cjphers),譬如 A 以 D 代换,B 以 E 代换,依此类推。但是移位密码很容易被破解,只要多进行几次反代换,或是分析字母出现的频率,就可找出原始有意义之资料,改善的方法是使用随机代换法,例如这次的 A 以 D代换,下次再遇到 A 就以 T 或任何其它字母来代换,要做到这种随机代换功能必须要求随机数产生器能产生重复的随机数序列以作为译码之用,在 VB 中要产生重复的随机数序列必须使用 Randomize Rnd(一个负数) 来初始化随机数产生器,关于随机代换密码法可参考 和硕出版的 "VB 5.0/6.0 程序设计圣经" 这本书的第十七章。另一种常见的加密编码技巧是先求出每个字符的 ASCII 值,再将这些值作移位或 XOR 等处理,关于这种编码方法可以参考 MS Press 出版的 "VB6.0 进阶程序设计实务" 这本书的第十八章。

不知大家看过 "骇客任务(The Matrix)" 没?前阵子跟同学去看这部片,看得一头雾煞煞,很难看懂导演要表达什么 @_@。这里要介绍另一种编码法就是跟 Matrix 有关,但是却很容易懂,此法为 Hill 在 1926 年首度提出,本来我也不知道这种矩阵编码法,后来是我的一个纽西兰网友 Eileen 问我一个关于矩阵的问题才发现这种方法也能编码,在这特别感谢 Eileen 激发我的灵感 :)。

假设 M 是一个可逆方阵(invertible square matrix),A是欲编码之原始数据之 ASCII 值,则:

M×A=B

B 即为加密编码后的资料,译码的过程就是将 M 的逆矩阵 M-1 乘上 B 即可得到原始资料 A。 

A=M-1×M×A=M-1×B

以一个实例来说明,假设:

M = 1 2
3 4

则利用本站的 Matrix Inversion including determinant calculation by Gauss-Jordan Elimination with maximization of pivot elements. 可以求出 M 的逆矩阵 M-1:

M-1 = -2 1
1.5 -0.5

若欲加密编码之数据为 "book",利用 VB 的 AscW 函数可以求出其 ASCII 值为 98 111 111 107,现在将 M 乘上 A,由于必须符合矩阵乘法的原则,M 为 n×n,因此我们选定 A 为 n×1,这里的 n=2。

M×A = 1 2 × 98 = 320 = B
3 4 111 738

M×A = 1 2 × 111 = 325 = B
3 4 107 761

320 738 325 761 即为加密编码后之数据,欲反求得原始数据 A,只要将 M-1 乘上加密后之资料 B 即可。

M-1×B = -2 1 × 320 = 98 = A
1.5 -0.5 738 111

M-1×B = -2 1 × 325 = 111 = A
1.5 -0.5 761 107

再将求得的 98 111 111 107,以 ChrW 函数转换后即可知原始数据为 "book"。

 

子程序:

Public Sub encode(strSource As String, M() As Double, dblCoded() As Double)
  Dim i As Long, j As Long, n As Long, temp As Long, strM() As Double, strC() As Double
  n = UBound(M, 2)
  temp = Len(strSource) Mod n
  strSource = strSource & String(IIf(temp = 0, 0, n - temp), " ")
  ReDim strM(1 To n, 1 To 1) , strC(1 To n, 1 To 1) , dblCoded(1 To Len(strSource))
  For i = 1 To Len(strSource)
    If i Mod n = 0 Then
      strM(n, 1) = AscW(Mid(strSource, i, 1))
      Call MatrixMultiply(M, strM, strC)
      For j = 1 To n
        dblCoded(i + j - n) = strC(j, 1)
      Next
    Else
      strM(i Mod n, 1) = AscW(Mid(strSource, i, 1))
    End If
  Next
End Sub

Public Sub decode(strSource As String, iM() As Double, dblCoded() As Double)
Dim i As Long, j As Long, n As Long, strM() As Double, strC() As Double
n = UBound(iM, 2)
ReDim strM(1 To n, 1 To 1) As Double, strC(1 To n, 1 To 1) As Double
For i = 1 To UBound(dblCoded, 1)
If i Mod n = 0 Then
strM(n, 1) = dblCoded(i)
Call MatrixMultiply(iM, strM, strC)
For j = 1 To n
strSource = strSource & ChrW(CLng(strC(j, 1)))
Next
Else
strM(i Mod n, 1) = dblCoded(i)
End If
Next
End Sub
其中 MatrixMultiply 这个子程序,请参阅本站的 矩阵的基本运算(加、减、乘、转置、判断是否对称)

 

范例:

譬如欲将 "Visual Basic 实战网" 这个字符串加密编码,分别以 2 阶及 3 阶方阵来处理,其程序代码以及输出结果如下:

Private Sub Command1_Click()
Dim want() As Double, i, strWant As String
Dim M(1 To 2, 1 To 2) As Double, iM(1 To 2, 1 To 2) As Double
M(1, 1) = 1: M(1, 2) = 2: M(2, 1) = 3: M(2, 2) = 4
iM(1, 1) = -2: iM(1, 2) = 1: iM(2, 1) = 1.5: iM(2, 2) = -0.5
Call encode("Visual Basic 实战网", M, want)
For i = 1 To UBound(want)
Debug.Print want(i);
Next
Call decode(strWant, iM, want)
Debug.Print vbCrLf; strWant
End Sub

296 678 349 813 313 723 164 360 327 751 303 711 47084 94200 89492 204120 
Visual Basic 实战网

Private Sub Command2_Click()
Dim want() As Double, i, strWant As String
Dim M(1 To 3, 1 To 3) As Double, iM(1 To 3, 1 To 3) As Double
M(1, 1) = 1: M(1, 2) = 2: M(1, 3) = 3: M(2, 1) = 4: M(2, 2) = 5
M(2, 3) = 6: M(3, 1) = 7: M(3, 2) = 8: M(3, 3) = 10
iM(1, 1) = -0.666666667: iM(1, 2) = -1.333333333: iM(1, 3) = 1
iM(2, 1) = -0.666666667: iM(2, 2) = 3.666666667: iM(2, 3) = -2
iM(3, 1) = 1: iM(3, 2) = -2: iM(3, 3) = 1
Call encode("Visual Basic 实战网", M, want)
For i = 1 To UBound(want)
Debug.Print want(i);
Next
Call decode(strWant, iM, want)
Debug.Print vbCrLf; strWant
End Sub

641 1559 2592 635 1601 2675 455 1040 1722 622 1579 2635 122492 268574 439792 32338 129064 225822 
Visual Basic 实战网 

综上所述可知,可逆方阵 M 是这种编码与译码法的关键所在,M 的阶数愈高,加密编码后之数据就愈复杂,然而要指定一个可逆方阵 M 实属不易,实用上可要求使用者输入一密码,利用这个密码来求出可逆方阵 M。

此种方法其加密编码后之资料皆为数字,若要增加其保密性,可将这些数字再做进一步处理,并用 ChrW 转换成文字,但是必须注意转换后之文字必须是可显示的(displayable)、可打印的(printable),否则将无法储存至档案中。

这里只是示范一种矩阵加密编码技巧,若您需要完整的密码应用程序,可以参考 MS Press 出版的 "VB6.0 进阶程序设计实务" 这本书的第三十四章。

#2




呵呵~异或的方法被老板识破了~~

#3



异或有什么不好!!!

#4


To stukov2002(卡拉是头猪) 正确给你多加分
To pzytony(507) 那是懒人才用的法子,我懒,所以被识破,呵呵。
To 顶楼的师傅,有C的吗C++也成,我一看VB就想吃药片儿。

#5




有个办法~
#include <conio.h>
#include <memory.h>
#include <string.h>
#include <stdio.h>

void main()
{
    char    szInput[80];
    char    szOutput[80];
    int     n, nLen;

    // 输入待加密字符串.
    printf("Input string:");
    gets(szInput);
    nLen = strlen(szInput);

    // 加密.
    for(n = 0; n < nLen; n ++)
    {
        if(szInput[n] % 2) szOutput[n] = szInput[n] - 1;
        else szOutput[n] = szInput[n] + 1;
    }
    szOutput[n] = 0;
    // 输出加密后的字符串.
    printf("Output string:%s\n", szOutput);

    // 清空保存源串的字符数组.
    memset(szInput, 0, 80 * sizeof(char));

    // 解密.
    for(n = 0; n < nLen; n ++)
    {
        if(szOutput[n] % 2) szInput[n] = szOutput[n] - 1;
        else szInput[n] = szOutput[n] - 1;
    }
    szInput[n] = 0;
    // 输出源串.
    printf("Source string:%s\n", szInput);
}

输出:
Input string:Hello,World!
Output string:Idmmn-Vnsme 
Source string:Hello,World!

原理很简陋啊~
ascii码为奇数则输出字符的ascii码加一,否则减一~
要是再被识破了...不要赖我哦~~:D

#6


OK,谢了先。
我copy下来试试。
马上给分!

老板白痴!哈哈哈哈

#1


转,矩阵加密法,用的VB的语法,但你一定能看懂。

简易的矩阵加密编码法(cipher) 
当储存一项机密的资料(譬如:密码)于档案中或是 Windows 的系统登录区(registry)中,通常不希望被别人直接看到资料内容,于是就必须对该资料作加密编码的处理后再储存之,欲取用时唯有知道加密编码算法的人才能将编码过的资料译码成原始资料。已知最早的加密编码法都是使用简单的代换法,也就是所谓的移位密码(shift cjphers),譬如 A 以 D 代换,B 以 E 代换,依此类推。但是移位密码很容易被破解,只要多进行几次反代换,或是分析字母出现的频率,就可找出原始有意义之资料,改善的方法是使用随机代换法,例如这次的 A 以 D代换,下次再遇到 A 就以 T 或任何其它字母来代换,要做到这种随机代换功能必须要求随机数产生器能产生重复的随机数序列以作为译码之用,在 VB 中要产生重复的随机数序列必须使用 Randomize Rnd(一个负数) 来初始化随机数产生器,关于随机代换密码法可参考 和硕出版的 "VB 5.0/6.0 程序设计圣经" 这本书的第十七章。另一种常见的加密编码技巧是先求出每个字符的 ASCII 值,再将这些值作移位或 XOR 等处理,关于这种编码方法可以参考 MS Press 出版的 "VB6.0 进阶程序设计实务" 这本书的第十八章。

不知大家看过 "骇客任务(The Matrix)" 没?前阵子跟同学去看这部片,看得一头雾煞煞,很难看懂导演要表达什么 @_@。这里要介绍另一种编码法就是跟 Matrix 有关,但是却很容易懂,此法为 Hill 在 1926 年首度提出,本来我也不知道这种矩阵编码法,后来是我的一个纽西兰网友 Eileen 问我一个关于矩阵的问题才发现这种方法也能编码,在这特别感谢 Eileen 激发我的灵感 :)。

假设 M 是一个可逆方阵(invertible square matrix),A是欲编码之原始数据之 ASCII 值,则:

M×A=B

B 即为加密编码后的资料,译码的过程就是将 M 的逆矩阵 M-1 乘上 B 即可得到原始资料 A。 

A=M-1×M×A=M-1×B

以一个实例来说明,假设:

M = 1 2
3 4

则利用本站的 Matrix Inversion including determinant calculation by Gauss-Jordan Elimination with maximization of pivot elements. 可以求出 M 的逆矩阵 M-1:

M-1 = -2 1
1.5 -0.5

若欲加密编码之数据为 "book",利用 VB 的 AscW 函数可以求出其 ASCII 值为 98 111 111 107,现在将 M 乘上 A,由于必须符合矩阵乘法的原则,M 为 n×n,因此我们选定 A 为 n×1,这里的 n=2。

M×A = 1 2 × 98 = 320 = B
3 4 111 738

M×A = 1 2 × 111 = 325 = B
3 4 107 761

320 738 325 761 即为加密编码后之数据,欲反求得原始数据 A,只要将 M-1 乘上加密后之资料 B 即可。

M-1×B = -2 1 × 320 = 98 = A
1.5 -0.5 738 111

M-1×B = -2 1 × 325 = 111 = A
1.5 -0.5 761 107

再将求得的 98 111 111 107,以 ChrW 函数转换后即可知原始数据为 "book"。

 

子程序:

Public Sub encode(strSource As String, M() As Double, dblCoded() As Double)
  Dim i As Long, j As Long, n As Long, temp As Long, strM() As Double, strC() As Double
  n = UBound(M, 2)
  temp = Len(strSource) Mod n
  strSource = strSource & String(IIf(temp = 0, 0, n - temp), " ")
  ReDim strM(1 To n, 1 To 1) , strC(1 To n, 1 To 1) , dblCoded(1 To Len(strSource))
  For i = 1 To Len(strSource)
    If i Mod n = 0 Then
      strM(n, 1) = AscW(Mid(strSource, i, 1))
      Call MatrixMultiply(M, strM, strC)
      For j = 1 To n
        dblCoded(i + j - n) = strC(j, 1)
      Next
    Else
      strM(i Mod n, 1) = AscW(Mid(strSource, i, 1))
    End If
  Next
End Sub

Public Sub decode(strSource As String, iM() As Double, dblCoded() As Double)
Dim i As Long, j As Long, n As Long, strM() As Double, strC() As Double
n = UBound(iM, 2)
ReDim strM(1 To n, 1 To 1) As Double, strC(1 To n, 1 To 1) As Double
For i = 1 To UBound(dblCoded, 1)
If i Mod n = 0 Then
strM(n, 1) = dblCoded(i)
Call MatrixMultiply(iM, strM, strC)
For j = 1 To n
strSource = strSource & ChrW(CLng(strC(j, 1)))
Next
Else
strM(i Mod n, 1) = dblCoded(i)
End If
Next
End Sub
其中 MatrixMultiply 这个子程序,请参阅本站的 矩阵的基本运算(加、减、乘、转置、判断是否对称)

 

范例:

譬如欲将 "Visual Basic 实战网" 这个字符串加密编码,分别以 2 阶及 3 阶方阵来处理,其程序代码以及输出结果如下:

Private Sub Command1_Click()
Dim want() As Double, i, strWant As String
Dim M(1 To 2, 1 To 2) As Double, iM(1 To 2, 1 To 2) As Double
M(1, 1) = 1: M(1, 2) = 2: M(2, 1) = 3: M(2, 2) = 4
iM(1, 1) = -2: iM(1, 2) = 1: iM(2, 1) = 1.5: iM(2, 2) = -0.5
Call encode("Visual Basic 实战网", M, want)
For i = 1 To UBound(want)
Debug.Print want(i);
Next
Call decode(strWant, iM, want)
Debug.Print vbCrLf; strWant
End Sub

296 678 349 813 313 723 164 360 327 751 303 711 47084 94200 89492 204120 
Visual Basic 实战网

Private Sub Command2_Click()
Dim want() As Double, i, strWant As String
Dim M(1 To 3, 1 To 3) As Double, iM(1 To 3, 1 To 3) As Double
M(1, 1) = 1: M(1, 2) = 2: M(1, 3) = 3: M(2, 1) = 4: M(2, 2) = 5
M(2, 3) = 6: M(3, 1) = 7: M(3, 2) = 8: M(3, 3) = 10
iM(1, 1) = -0.666666667: iM(1, 2) = -1.333333333: iM(1, 3) = 1
iM(2, 1) = -0.666666667: iM(2, 2) = 3.666666667: iM(2, 3) = -2
iM(3, 1) = 1: iM(3, 2) = -2: iM(3, 3) = 1
Call encode("Visual Basic 实战网", M, want)
For i = 1 To UBound(want)
Debug.Print want(i);
Next
Call decode(strWant, iM, want)
Debug.Print vbCrLf; strWant
End Sub

641 1559 2592 635 1601 2675 455 1040 1722 622 1579 2635 122492 268574 439792 32338 129064 225822 
Visual Basic 实战网 

综上所述可知,可逆方阵 M 是这种编码与译码法的关键所在,M 的阶数愈高,加密编码后之数据就愈复杂,然而要指定一个可逆方阵 M 实属不易,实用上可要求使用者输入一密码,利用这个密码来求出可逆方阵 M。

此种方法其加密编码后之资料皆为数字,若要增加其保密性,可将这些数字再做进一步处理,并用 ChrW 转换成文字,但是必须注意转换后之文字必须是可显示的(displayable)、可打印的(printable),否则将无法储存至档案中。

这里只是示范一种矩阵加密编码技巧,若您需要完整的密码应用程序,可以参考 MS Press 出版的 "VB6.0 进阶程序设计实务" 这本书的第三十四章。

#2




呵呵~异或的方法被老板识破了~~

#3



异或有什么不好!!!

#4


To stukov2002(卡拉是头猪) 正确给你多加分
To pzytony(507) 那是懒人才用的法子,我懒,所以被识破,呵呵。
To 顶楼的师傅,有C的吗C++也成,我一看VB就想吃药片儿。

#5




有个办法~
#include <conio.h>
#include <memory.h>
#include <string.h>
#include <stdio.h>

void main()
{
    char    szInput[80];
    char    szOutput[80];
    int     n, nLen;

    // 输入待加密字符串.
    printf("Input string:");
    gets(szInput);
    nLen = strlen(szInput);

    // 加密.
    for(n = 0; n < nLen; n ++)
    {
        if(szInput[n] % 2) szOutput[n] = szInput[n] - 1;
        else szOutput[n] = szInput[n] + 1;
    }
    szOutput[n] = 0;
    // 输出加密后的字符串.
    printf("Output string:%s\n", szOutput);

    // 清空保存源串的字符数组.
    memset(szInput, 0, 80 * sizeof(char));

    // 解密.
    for(n = 0; n < nLen; n ++)
    {
        if(szOutput[n] % 2) szInput[n] = szOutput[n] - 1;
        else szInput[n] = szOutput[n] - 1;
    }
    szInput[n] = 0;
    // 输出源串.
    printf("Source string:%s\n", szInput);
}

输出:
Input string:Hello,World!
Output string:Idmmn-Vnsme 
Source string:Hello,World!

原理很简陋啊~
ascii码为奇数则输出字符的ascii码加一,否则减一~
要是再被识破了...不要赖我哦~~:D

#6


OK,谢了先。
我copy下来试试。
马上给分!

老板白痴!哈哈哈哈