Data update
This commit is contained in:
parent
8e4e15fa56
commit
72eb4943cb
1853 changed files with 35514 additions and 9441 deletions
|
|
@ -0,0 +1,224 @@
|
|||
module vigenere_cipher
|
||||
use, intrinsic :: iso_fortran_env, only: real64, int32
|
||||
implicit none
|
||||
|
||||
private
|
||||
public :: vigenere_decrypt
|
||||
|
||||
type :: FreqPair
|
||||
character :: c
|
||||
real(real64) :: freq
|
||||
end type FreqPair
|
||||
|
||||
contains
|
||||
|
||||
function frequency(input_text, input_len) result(freq_result)
|
||||
integer(int32), intent(in) :: input_text(:), input_len
|
||||
type(FreqPair), allocatable :: freq_result(:)
|
||||
integer :: i
|
||||
|
||||
allocate(freq_result(26))
|
||||
do i = 1, 26
|
||||
freq_result(i)%c = achar(64 + i)
|
||||
freq_result(i)%freq = 0.0_real64
|
||||
end do
|
||||
|
||||
do i = 1, input_len
|
||||
freq_result(input_text(i) - 64)%freq = freq_result(input_text(i) - 64)%freq + 1
|
||||
end do
|
||||
end function frequency
|
||||
|
||||
function correlation(input_text, input_len, sorted_targets) result(corr)
|
||||
integer(int32), intent(in) :: input_text(:), input_len
|
||||
real(real64), intent(in) :: sorted_targets(:)
|
||||
real(real64) :: corr
|
||||
type(FreqPair), allocatable :: freq(:)
|
||||
integer :: i, j
|
||||
type(FreqPair) :: temp
|
||||
|
||||
freq = frequency(input_text, input_len)
|
||||
|
||||
! Sort freq by frequency
|
||||
do i = 1, 25
|
||||
do j = i + 1, 26
|
||||
if (freq(j)%freq > freq(i)%freq) then
|
||||
temp = freq(j)
|
||||
freq(j) = freq(i)
|
||||
freq(i) = temp
|
||||
end if
|
||||
end do
|
||||
end do
|
||||
|
||||
corr = 0.0_real64
|
||||
do i = 1, 26
|
||||
corr = corr + freq(i)%freq * sorted_targets(i)
|
||||
end do
|
||||
|
||||
deallocate(freq)
|
||||
end function correlation
|
||||
|
||||
subroutine vigenere_decrypt(target_freqs, encoded, out_key, out_text)
|
||||
implicit none
|
||||
real(real64), intent(in) :: target_freqs(:)
|
||||
character(len=*), intent(in) :: encoded
|
||||
character(len=:), allocatable, intent(out) :: out_key, out_text
|
||||
integer(int32), allocatable :: cleaned(:)
|
||||
integer :: cleaned_len, i, j, k, best_len, key_len, shift
|
||||
real(real64) :: best_corr, corr, max_corr
|
||||
real(real64), allocatable :: sorted_targets(:)
|
||||
integer(int32), allocatable :: pieces(:), piece_lens(:), current_piece(:)
|
||||
character(len=:), allocatable :: temp_key
|
||||
|
||||
! Clean input text
|
||||
allocate(cleaned(len(encoded)))
|
||||
cleaned_len = 0
|
||||
do i = 1, len(encoded)
|
||||
if (encoded(i:i) >= 'A' .and. encoded(i:i) <= 'Z') then
|
||||
cleaned_len = cleaned_len + 1
|
||||
cleaned(cleaned_len) = iachar(encoded(i:i))
|
||||
end if
|
||||
end do
|
||||
|
||||
! Sort target frequencies
|
||||
allocate(sorted_targets(26))
|
||||
sorted_targets = target_freqs
|
||||
call sort_array(sorted_targets)
|
||||
|
||||
! Find best key length
|
||||
best_len = 0
|
||||
best_corr = -100.0_real64
|
||||
|
||||
do key_len = 2,cleaned_len/20
|
||||
allocate(pieces(cleaned_len), piece_lens(key_len))
|
||||
pieces = cleaned
|
||||
piece_lens = 0
|
||||
do j = 1, cleaned_len
|
||||
piece_lens(mod(j-1, key_len) + 1) = piece_lens(mod(j-1, key_len) + 1) + 1
|
||||
end do
|
||||
|
||||
corr = -0.5_real64 * key_len
|
||||
do i = 1, key_len
|
||||
allocate(current_piece(piece_lens(i)))
|
||||
k = 0
|
||||
do j = i, cleaned_len, key_len
|
||||
k = k + 1
|
||||
current_piece(k) = pieces(j)
|
||||
end do
|
||||
corr = corr + correlation(current_piece, piece_lens(i), sorted_targets)
|
||||
deallocate(current_piece)
|
||||
end do
|
||||
|
||||
if (corr > best_corr) then
|
||||
best_len = key_len
|
||||
best_corr = corr
|
||||
end if
|
||||
|
||||
deallocate(pieces, piece_lens)
|
||||
end do
|
||||
|
||||
! Find key
|
||||
allocate(character(len=best_len) :: temp_key)
|
||||
do i = 1, best_len
|
||||
allocate(pieces(cleaned_len/best_len + 1))
|
||||
k = 0
|
||||
do j = i, cleaned_len, best_len
|
||||
k = k + 1
|
||||
pieces(k) = cleaned(j)
|
||||
end do
|
||||
|
||||
max_corr = 0.0_real64
|
||||
do concurrent (shift = 0:25)
|
||||
corr = 0.0_real64
|
||||
do j = 1, k
|
||||
corr = corr + target_freqs(mod(pieces(j) - 65 - shift + 26, 26) + 1)
|
||||
end do
|
||||
if (corr > max_corr) then
|
||||
max_corr = corr
|
||||
temp_key(i:i) = achar(shift + 65)
|
||||
end if
|
||||
end do
|
||||
deallocate(pieces)
|
||||
end do
|
||||
out_key = temp_key
|
||||
|
||||
! Decrypt
|
||||
allocate(character(len=cleaned_len) :: out_text)
|
||||
do i = 1, cleaned_len
|
||||
k = iachar(out_key(mod(i-1, best_len) + 1:mod(i-1, best_len) + 1)) - 65
|
||||
out_text(i:i) = achar(mod(cleaned(i) - 65 - k + 26, 26) + 65)
|
||||
end do
|
||||
end subroutine vigenere_decrypt
|
||||
|
||||
subroutine sort_array(arr)
|
||||
real(real64), intent(inout) :: arr(:)
|
||||
integer :: i, j
|
||||
real(real64) :: temp
|
||||
|
||||
do i = 1, size(arr) - 1
|
||||
do j = i + 1, size(arr)
|
||||
if (arr(j) > arr(i)) then
|
||||
temp = arr(j)
|
||||
arr(j) = arr(i)
|
||||
arr(i) = temp
|
||||
end if
|
||||
end do
|
||||
end do
|
||||
end subroutine sort_array
|
||||
|
||||
end module vigenere_cipher
|
||||
|
||||
program main
|
||||
use vigenere_cipher
|
||||
use, intrinsic :: iso_fortran_env, only: real64
|
||||
implicit none
|
||||
|
||||
real(real64) :: english_freqs(26) = [ &
|
||||
0.08167, 0.01492, 0.02782, 0.04253, 0.12702, 0.02228, 0.02015, &
|
||||
0.06094, 0.06966, 0.00153, 0.00772, 0.04025, 0.02406, 0.06749, &
|
||||
0.07507, 0.01929, 0.00095, 0.05987, 0.06327, 0.09056, 0.02758, &
|
||||
0.00978, 0.02360, 0.00150, 0.01974, 0.00074 ]
|
||||
|
||||
character(len=*), parameter :: encoded = &
|
||||
"MOMUD EKAPV TQEFM OEVHP AJMII CDCTI FGYAG JSPXY ALUYM NSMYH" // &
|
||||
"VUXJE LEPXJ FXGCM JHKDZ RYICU HYPUS PGIGM OIYHF WHTCQ KMLRD" // &
|
||||
"ITLXZ LJFVQ GHOLW CUHLO MDSOE KTALU VYLNZ RFGBX PHVGA LWQIS" // &
|
||||
"FGRPH JOOFW GUBYI LAPLA LCAFA AMKLG CETDW VOELJ IKGJB XPHVG" // &
|
||||
"ALWQC SNWBU BYHCU HKOCE XJEYK BQKVY KIIEH GRLGH XEOLW AWFOJ" // &
|
||||
"ILOVV RHPKD WIHKN ATUHN VRYAQ DIVHX FHRZV QWMWV LGSHN NLVZS" // &
|
||||
"JLAKI FHXUF XJLXM TBLQV RXXHR FZXGV LRAJI EXPRV OSMNP KEPDT" // &
|
||||
"LPRWM JAZPK LQUZA ALGZX GVLKL GJTUI ITDSU REZXJ ERXZS HMPST" // &
|
||||
"MTEOE PAPJH SMFNB YVQUZ AALGA YDNMP AQOWT UHDBV TSMUE UIMVH" // &
|
||||
"QGVRW AEFSP EMPVE PKXZY WLKJA GWALT VYYOB YIXOK IHPDS EVLEV" // &
|
||||
"RVSGB JOGYW FHKBL GLXYA MVKIS KIEHY IMAPX UOISK PVAGN MZHPW" // &
|
||||
"TTZPV XFCCD TUHJH WLAPF YULTB UXJLN SIJVV YOVDJ SOLXG TGRVO" // &
|
||||
"SFRII CTMKO JFCQF KTINQ BWVHG TENLH HOGCS PSFPV GJOKM SIFPR" // &
|
||||
"ZPAAS ATPTZ FTPPD PORRF TAXZP KALQA WMIUD BWNCT LEFKO ZQDLX" // &
|
||||
"BUXJL ASIMR PNMBF ZCYLV WAPVF QRHZV ZGZEF KBYIO OFXYE VOWGB" // &
|
||||
"BXVCB XBAWG LQKCM ICRRX MACUO IKHQU AJEGL OIJHH XPVZW JEWBA" // &
|
||||
"FWAML ZZRXJ EKAHV FASMU LVVUT TGK"
|
||||
|
||||
character(len=:), allocatable :: key, decoded
|
||||
integer :: xx,yy
|
||||
call system_clock(count=xx)
|
||||
|
||||
call vigenere_decrypt(english_freqs, encoded, key, decoded)
|
||||
call system_clock(count=yy)
|
||||
|
||||
print *, "Key: ", key
|
||||
print *, "Decoded text: "
|
||||
|
||||
block
|
||||
INTEGER :: start, end, length, chunk_size
|
||||
! Define the chunk size
|
||||
chunk_size = 80
|
||||
! Get the length of the string
|
||||
length = LEN_TRIM(decoded)
|
||||
|
||||
! Print the string in chunks of 80 characters
|
||||
DO start = 1, length, chunk_size
|
||||
end = MIN(start + chunk_size - 1, length)
|
||||
PRINT *, decoded(start:end)
|
||||
END DO
|
||||
end block
|
||||
print '(/,a,1x,i0,1x,a)', 'Decoded in =',(yy-xx), 'milliseconds'
|
||||
end program main
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
Type FreqPair
|
||||
As String * 1 c
|
||||
As Double freq
|
||||
End Type
|
||||
|
||||
Function frequency(inputText() As Integer, inputLen As Integer) As FreqPair Ptr
|
||||
Dim As FreqPair Ptr result = Callocate(26 * Sizeof(FreqPair))
|
||||
Dim As Integer i
|
||||
|
||||
For i = 0 To 25
|
||||
result[i].c = Chr(65 + i)
|
||||
result[i].freq = 0.0
|
||||
Next
|
||||
|
||||
For i = 0 To inputLen - 1
|
||||
result[inputText(i) - 65].freq += 1
|
||||
Next
|
||||
|
||||
Return result
|
||||
End Function
|
||||
|
||||
Function correlation(inputText() As Integer, inputLen As Integer, sorted_targets() As Double) As Double
|
||||
Dim As FreqPair Ptr freq = frequency(inputText(), inputLen)
|
||||
Dim As Integer i, j
|
||||
Dim As Double result = 0.0
|
||||
|
||||
'Sort freq by frequency
|
||||
For i = 0 To 24
|
||||
For j = i + 1 To 25
|
||||
If freq[j].freq > freq[i].freq Then Swap freq[j], freq[i]
|
||||
Next
|
||||
Next
|
||||
|
||||
For i = 0 To 25
|
||||
result += freq[i].freq * sorted_targets(i)
|
||||
Next
|
||||
|
||||
Deallocate(freq)
|
||||
Return result
|
||||
End Function
|
||||
|
||||
Sub vigenereDecrypt(targetFreqs() As Double, encoded As String, Byref outKey As String, Byref outText As String)
|
||||
Dim As Integer cleaned(Len(encoded))
|
||||
Dim As Integer cleanedLen = 0
|
||||
Dim As Integer i, j, k
|
||||
|
||||
'Clean inputText
|
||||
For i = 1 To Len(encoded)
|
||||
Dim As String c = Mid(encoded, i, 1)
|
||||
If c >= "A" And c <= "Z" Then
|
||||
cleaned(cleanedLen) = Asc(c)
|
||||
cleanedLen += 1
|
||||
End If
|
||||
Next
|
||||
|
||||
'Sort target frequencies
|
||||
Dim As Double sorted_targets(25)
|
||||
For i = 0 To 25
|
||||
sorted_targets(i) = targetFreqs(i)
|
||||
Next
|
||||
For i = 0 To 24
|
||||
For j = i + 1 To 25
|
||||
If sorted_targets(j) > sorted_targets(i) Then Swap sorted_targets(j), sorted_targets(i)
|
||||
Next
|
||||
Next
|
||||
|
||||
'Find best key length
|
||||
Dim As Integer bestLen = 0
|
||||
Dim As Double bestCorr = -100.0
|
||||
|
||||
For keyLen As Integer = 2 To cleanedLen \ 20
|
||||
Dim As Integer pieces(cleanedLen)
|
||||
Dim As Integer pieceLens(keyLen)
|
||||
|
||||
For j = 0 To cleanedLen - 1
|
||||
pieces(j) = cleaned(j)
|
||||
pieceLens(j Mod keyLen) += 1
|
||||
Next
|
||||
|
||||
Dim As Double corr = -0.5 * keyLen
|
||||
For i = 0 To keyLen - 1
|
||||
Dim As Integer currentPiece(cleanedLen)
|
||||
Dim As Integer currentLen = 0
|
||||
|
||||
For j = i To cleanedLen - 1 Step keyLen
|
||||
currentPiece(currentLen) = pieces(j)
|
||||
currentLen += 1
|
||||
Next
|
||||
|
||||
corr += correlation(currentPiece(), currentLen, sorted_targets())
|
||||
Next
|
||||
|
||||
If corr > bestCorr Then
|
||||
bestLen = keyLen
|
||||
bestCorr = corr
|
||||
End If
|
||||
Next
|
||||
|
||||
'Find key
|
||||
outKey = ""
|
||||
For i = 0 To bestLen - 1
|
||||
Dim As Integer piece(cleanedLen)
|
||||
Dim As Integer pieceLen = 0
|
||||
|
||||
For j = i To cleanedLen - 1 Step bestLen
|
||||
piece(pieceLen) = cleaned(j)
|
||||
pieceLen += 1
|
||||
Next
|
||||
|
||||
Dim As Double maxCorr = 0.0
|
||||
Dim As Integer bestShift = 0
|
||||
|
||||
For shift As Integer = 0 To 25
|
||||
Dim As Double corr = 0.0
|
||||
For j = 0 To pieceLen - 1
|
||||
k = (piece(j) - 65 - shift + 26) Mod 26
|
||||
corr += targetFreqs(k)
|
||||
Next
|
||||
If corr > maxCorr Then
|
||||
maxCorr = corr
|
||||
bestShift = shift
|
||||
End If
|
||||
Next
|
||||
|
||||
outKey += Chr(bestShift + 65)
|
||||
Next
|
||||
|
||||
'Decrypt
|
||||
outText = ""
|
||||
For i = 0 To cleanedLen - 1
|
||||
k = Asc(Mid(outKey, (i Mod bestLen) + 1, 1)) - 65
|
||||
outText &= Chr(((cleaned(i) - 65 - k + 26) Mod 26) + 65)
|
||||
Next
|
||||
End Sub
|
||||
|
||||
'Main program
|
||||
Dim As Double english_freqs(25) = { _
|
||||
0.08167, 0.01492, 0.02782, 0.04253, 0.12702, 0.02228, 0.02015, _
|
||||
0.06094, 0.06966, 0.00153, 0.00772, 0.04025, 0.02406, 0.06749, _
|
||||
0.07507, 0.01929, 0.00095, 0.05987, 0.06327, 0.09056, 0.02758, _
|
||||
0.00978, 0.02360, 0.00150, 0.01974, 0.00074 }
|
||||
|
||||
Dim As String encoded = _
|
||||
"MOMUD EKAPV TQEFM OEVHP AJMII CDCTI FGYAG JSPXY ALUYM NSMYH" & _
|
||||
"VUXJE LEPXJ FXGCM JHKDZ RYICU HYPUS PGIGM OIYHF WHTCQ KMLRD" & _
|
||||
"ITLXZ LJFVQ GHOLW CUHLO MDSOE KTALU VYLNZ RFGBX PHVGA LWQIS" & _
|
||||
"FGRPH JOOFW GUBYI LAPLA LCAFA AMKLG CETDW VOELJ IKGJB XPHVG" & _
|
||||
"ALWQC SNWBU BYHCU HKOCE XJEYK BQKVY KIIEH GRLGH XEOLW AWFOJ" & _
|
||||
"ILOVV RHPKD WIHKN ATUHN VRYAQ DIVHX FHRZV QWMWV LGSHN NLVZS" & _
|
||||
"JLAKI FHXUF XJLXM TBLQV RXXHR FZXGV LRAJI EXPRV OSMNP KEPDT" & _
|
||||
"LPRWM JAZPK LQUZA ALGZX GVLKL GJTUI ITDSU REZXJ ERXZS HMPST" & _
|
||||
"MTEOE PAPJH SMFNB YVQUZ AALGA YDNMP AQOWT UHDBV TSMUE UIMVH" & _
|
||||
"QGVRW AEFSP EMPVE PKXZY WLKJA GWALT VYYOB YIXOK IHPDS EVLEV" & _
|
||||
"RVSGB JOGYW FHKBL GLXYA MVKIS KIEHY IMAPX UOISK PVAGN MZHPW" & _
|
||||
"TTZPV XFCCD TUHJH WLAPF YULTB UXJLN SIJVV YOVDJ SOLXG TGRVO" & _
|
||||
"SFRII CTMKO JFCQF KTINQ BWVHG TENLH HOGCS PSFPV GJOKM SIFPR" & _
|
||||
"ZPAAS ATPTZ FTPPD PORRF TAXZP KALQA WMIUD BWNCT LEFKO ZQDLX" & _
|
||||
"BUXJL ASIMR PNMBF ZCYLV WAPVF QRHZV ZGZEF KBYIO OFXYE VOWGB" & _
|
||||
"BXVCB XBAWG LQKCM ICRRX MACUO IKHQU AJEGL OIJHH XPVZW JEWBA" & _
|
||||
"FWAML ZZRXJ EKAHV FASMU LVVUT TGK"
|
||||
|
||||
Dim As String key, decoded
|
||||
vigenereDecrypt(english_freqs(), encoded, key, decoded)
|
||||
|
||||
Print "Key: "; key
|
||||
Print !"\nDecoded text: "; decoded
|
||||
|
||||
Sleep
|
||||
Loading…
Add table
Add a link
Reference in a new issue