首先,互联网上的大多数文章看起来如此迟钝的原因是它们似乎都来自少数专利申请。新公式和算法的专利申请似乎总是隐藏着一些东西,因为它们确实如此。众所周知,监管此类东西的未经许可的使用非常困难,申请人试图跨越专利保护和商业秘密保护之间的界限。这里的要点是,这并不一定意味着这都是废话。
其次,我所知道的所有分形映射在某种程度上都是“有损的”,因为映射不是严格的 1 对 1。虽然这是相信没有有效方法来破解代码的充分理由,但它也意味着任何直接由有损分形“加密”的东西都无法解密,即使使用密钥也是如此。因此,任何类型的直接分形哈希都是不可逆的。
因此,分形加密不能意味着消息本身是directly用分形加密。相反,它必须意味着分形被用作“主密钥”,以能够同时生成“本地”或“顺序”密钥,然后使用这些密钥来加密和解密实际消息。
在进一步讨论之前,让我们回顾一下加密的基础知识:
加密算法原理
假设您有一系列消息 M(j)(j=1 到 N),您希望能够安全地将其传输到接收方。您需要一个可逆加密函数 E,如下所示:
E(M(j), k) --> X(j)
其中 (k) 是加密密钥,X(j) 是相应的加密消息。然后消息被传输到我们的接收者,接收者具有互补函数 E' 来解密加密的消息:
E'(X(j), k) --> M(j)
但是,据我所知,您不能使用分形同时创建 E() 和 E'() 函数。另一方面,有一些函数(例如 XOR)是它们自己的补充:
( M(j) XOR k ) --> X(j) *and also* ( X(j) XOR k ) --> M(j)
但 XOR 也是一种弱加密函数,虽然它对于单个消息来说是完全安全的,但如果我们使用相同的密钥 (k) 多次使用它,则很容易进行逆向工程 (k),从而使 XOR 不安全用于单密钥加密系统。这可以通过每次使用不同的密钥来解决:
M(j) XOR K(j) --> X(j)
and
X(j) XOR K(j) --> M(j)
这解决了一个问题,但引入了另一个问题,即我们如何确保发送者和接收者拥有相同的一组密钥?传输一系列密钥并不是解决方案,因为这让我们回到了安全传输一系列消息的原始问题。
相反,我们希望在发送者和接收者上独立生成一系列相同的密钥。但我们需要能够生成一系列本身就加密安全的密钥。也就是说,即使外部观察者知道所有前面的键,他们仍然无法准确地预测该系列中的下一个键。而且因为我们每次都需要完全不同的密钥系列(以使它们不可猜测),所以我们实际上需要密钥系列本身是基于密钥的。
解决方案是使用主密钥 MK 和不同的加密函数 H 来为每条消息生成特定密钥:
H(MK, j) --> K(j); M(j) XOR K(j) --> X(j)
and
H(MK, j) --> K(j); X(j) XOR K(j) --> M(j)
这就是我们的分形的用武之地,因为正如我们在上面看到的,H 函数不需要补充函数 H'。因此,我们可以自由地使用基于分形的函数和主密钥来生成我们的一系列本地密钥。
示例实现及说明
下面是一个演示这种方法的 VB.NET 类,它是分形加密的简单实现:
Option Explicit On
Public Class FractalEncrypt
'Fractal Encryption / Decryption demo class'
' 2009-08-08 RBarryYoung Created.'
' note: '
' Property of R. Barry Young & Proactive Performance Solutions, Inc.,'
' protected under open source license'
Public Const CrLower As Double = 0.1
Public Const CrUpper As Double = Math.PI / (2 * Math.E)
Public Const CiLower As Double = 0.1
Public Const CiUpper As Double = Math.PI / (2 * Math.E)
Public ReadOnly Cr As Double, Ci As Double, Sr As Double, Si As Double
Public ReadOnly BaseSeq As Integer
Public Sub New(ByVal KeyR As Double, ByVal KeyI As Double, ByVal SaltR As Double _
, ByVal SaltI As Double, ByVal SeqStart As Integer)
Cr = ((KeyR - CrLower) Mod (CrUpper - CrLower)) + CrLower
Ci = ((KeyI - CiLower) Mod (CiUpper - CiLower)) + CiLower
Sr = ((SaltR - CrLower) Mod (CrUpper - CrLower)) + CrLower
Si = ((SaltI - CiLower) Mod (CiUpper - CiLower)) + CiLower
BaseSeq = SeqStart
End Sub
Public Function Encrypt(ByVal Text As String, ByVal Seq As Integer) As String
'Encrypt the string passed, adding on the sequence as a header.'
Debug.Print("Encrypt<" & Seq & ">" & Len(Text) & ":" & Text)
Dim CurSeq = BaseSeq + Seq
'make the sequence prefix'
Dim enc As String = Format(Seq, "000000000") & ":"
Dim EncryptedOffset As Integer = 0
Do While EncryptedOffset < Len(Text)
'encrypt each 4 characters separately'
enc = enc & Encrypt4(Text, EncryptedOffset, CurSeq)
EncryptedOffset = EncryptedOffset + 4
Loop
Return enc
End Function
Public Function Decrypt(ByVal CrypText As String) As String
'Decrypt the string passed, extracting the Sequence header first.'
'Extract the sequence'
Dim Seq As Integer = CInt(Left(CrypText, 9))
Dim CurSeq = BaseSeq + Seq
'Extract the encrypted message payload'
CrypText = Mid(CrypText, 11)
Debug.Print("Decrypt<" & Seq & ">" & Len(CrypText) & ":" & CrypText)
'Now decrypt it 4 characters at a time'
Dim txt As String = ""
Dim EncryptedOffset As Integer = 0
Do While EncryptedOffset < Len(CrypText)
'encrypt each 4 characters separately'
txt = txt & Encrypt4(CrypText, EncryptedOffset, CurSeq)
EncryptedOffset = EncryptedOffset + 4
Loop
Return txt
End Function
Public Function Encrypt4(ByVal text As String, ByVal StrOffs As Integer _
, ByVal CurSeq As Integer) As String
'Encrypt/Decrypt 4 characters of the string.'
' (note: encrypt and decrypt are the same because XOR is its own complement)'
Dim str As String = Mid(text, StrOffs + 1, 4)
Dim enc As String
'generate the seeds from the current message sequence and the current string offset'
'1. define complex Seq as (CurSeq, StrOffs)'
Dim SeedR As Double = (Sr * CurSeq) - (Si * StrOffs)
Dim SeedI As Double = (Sr * StrOffs) + (Si * CurSeq)
'2. remap the result back into the valid range'
SeedR = SeedR Mod (CrUpper - CrLower)
SeedI = SeedI Mod (CiUpper - CiLower)
'generate the local keys from the master keys'
Dim Zr As Double = SeedR, Zi As Double = SeedI
Dim r As Double, i As Double, zx As Integer = 0, zy As Integer = 0
'1. apply the julia formula 16 times to hash it up good.'
For j As Integer = 1 To 16
'Z(n+1) = Z(n)^2 - C:'
r = Zr * Zr - Zi * Zi - Cr
i = 2 * Zr * Zi - Ci
If Double.IsInfinity(r) Or Double.IsNaN(r) Then r = (zx \ zy) 'force an error'
If Double.IsInfinity(i) Or Double.IsNaN(i) Then i = (zx \ zy) 'force an error'
'put back into Z:'
Zr = r : Zi = i
Next
'2. remap the back into our results window'
Zr = ((Zr - CrLower) Mod (CrUpper - CrLower)) + CrLower
Zi = ((Zi - CiLower) Mod (CiUpper - CiLower)) + CiLower
'Form the local keys into the Mask Keys variables (M).'
Dim Mr As Integer, Mi As Integer
'1. scale them both into the range of about 2^30.'
Mr = CInt((1024 * 1024 * 1024) * (Zr - CrLower) / (CrUpper - CrLower))
Mi = CInt((1024 * 1024 * 1024) * (Zi - CiLower) / (CiUpper - CiLower))
'2. only use the lower 16 bits that are left:'
Mr = Mr And 65535 : Mi = Mi And 65535
'encode the current 4 characters as a 2 * 2-byte integer'
Dim R2 As Integer, I2 As Integer
If StrOffs + 1 <= Len(text) Then R2 = Asc(Mid(text, StrOffs + 1, 1))
If StrOffs + 2 <= Len(text) Then R2 = R2 + 256 * Asc(Mid(text, StrOffs + 2, 1))
If StrOffs + 3 <= Len(text) Then I2 = Asc(Mid(text, StrOffs + 3, 1))
If StrOffs + 4 <= Len(text) Then I2 = I2 + 256 * Asc(Mid(text, StrOffs + 4, 1))
'Encrypt (or Decrypt) the data by masking it with the local Keys'
R2 = R2 Xor Mr
I2 = I2 Xor Mi
'recode them as ascii strings again:'
enc = Chr(R2 And 255) & Chr(R2 \ 256) & Chr(I2 And 255) & Chr(I2 \ 256)
Return enc
End Function
End Class
完整的 Visual Studio Windows 项目和 Windows exe 可以在以下位置找到:http://www.codeplex.com/FractalEncryptDemo http://www.codeplex.com/FractalEncryptDemo
此类使用基于复平面中的二次递归 Z(i+1) = Z(i)^2 - C 的 Julia 集。生成的主密钥由 5 个数字、4 个 0 到 1 之间的双精度浮点值和 1 个 1 到 1,000,000,000 之间的整数组成。前两个 double 值定义了上式中 C 的实部和虚部。后两个双精度数定义用于生成起始 Z 的种子值的实部和虚部。
这两个值都被映射(通过模运算)到从 (0.1, 0.1) 到大约 (0.55, 0.55) 的小正方形区域。这样做是为了尝试确保我们的分形计算不会溢出或下溢(尽管我不确定这是否仍然可能)。最后,整数值用作序列值的偏移量(上面公式中的“j”)。
消息一次编码为四个 ASCII 字符。首先,将序列号 (j) 添加到序列偏移量中,该序列偏移量与消息中的 4 字节偏移量一起作为复数使用,该复数乘以复数种子值,然后重新映射回活动矩形以获得我们的起始 Z 值。然后 Julia 集合递归 (Z = Z^2 + C) 应用 16 次,最终结果再次重新映射回活动矩形。
然后将最终的复数值乘以 2^30,实部和虚部都转换为整数,然后使用每个的底部 16 位来提供本地密钥的 32 位(4 字节)。然后,在发送方将其与相应的 4 个消息字节进行异或以对其进行加密,或者在接收方将其与加密文本进行异或以将其解密。