This repository has been archived by the owner on Apr 5, 2022. It is now read-only.
forked from wmoss/haskell-Crypto
-
Notifications
You must be signed in to change notification settings - Fork 1
/
SymmetricTest.hs
232 lines (200 loc) · 6.55 KB
/
SymmetricTest.hs
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
module Main(main) where
import Codec.Utils
import Codec.Encryption.Blowfish as Blowfish
import Codec.Encryption.Modes
import Codec.Encryption.Padding
import Codec.Encryption.DES as DES
import Codec.Encryption.AES as AES
import Data.Word
import Data.Bits
import Data.Char
import Data.LargeWord
import Test.HUnit
import Numeric
-- AES Tests.
-- Comparision with resuts from
-- http://www.cs.ucsd.edu/~fritz/rijndael_test.html
ad = 0xF0E1D2C3B4A5968778695A4B3C2D1E0F :: Word128
ak16 = 0xF0E1D2C3B4A5968778695A4B3C2D1E0F :: Word128
ae16 = 0x6e94fffbb861b2c1769cd4629f3d724b :: Word128
ae16' = AES.encrypt ak16 ad
aesTest1 =
TestCase (
assertEqual "AES Key Length 128" ae16 ae16'
)
ak24 = 0xF0E1D2C3B4A5968778695A4B3C2D1E0FF0E1D2C3B4A59687 :: Word192
ae24' = AES.encrypt ak24 ad
ae24 = 0x07d806bb62ebb4399354594ea6586ec6 :: Word128
aesTest2 =
TestCase (
assertEqual "AES Key Length 192" ae24 ae24'
)
ak32 = 0xF0E1D2C3B4A5968778695A4B3C2D1E0FF0E1D2C3B4A5968778695A4B3C2D1E0F :: Word256
ae32' = AES.encrypt ak32 ad
ae32 = 0x28e88482d9b146fdde7e080fcbae1b98 :: Word128
aes3 = ae32 == ae32'
aesTest3 =
TestCase (
assertEqual "AES Key Length 256" ae32 ae32'
)
-- Comparision with resuts from
-- http://www.zvon.org/tmRFC/RFC3602/Output/chapter4.html
aeskey16 = 0x06a9214036b8a15b512e03d534120006 :: Word128
aesiv16 = 0x3dafba429d9eb430b422da802c9fac41 :: Word128
aesplaintext = "Single block msg"
aesciphertext = [0xe353779c1079aeb82708942dbe77181a] :: [Word128]
aesciphertext' =
cbc AES.encrypt aesiv16 aeskey16 $
pkcs5 $
map (fromIntegral . ord) aesplaintext
-- aescbc1 = aesciphertext == take 1 aesciphertext'
aescbcTest1 =
TestCase (
assertEqual "AES CBC PKCS5 Key Length 128"
aesciphertext (take 1 aesciphertext')
)
aesplaintext' =
map (chr . fromIntegral) $
unPkcs5 $
unCbc AES.decrypt aesiv16 aeskey16 aesciphertext'
aescbcTest2 =
TestCase (
assertEqual "AES CBC PKCS5 Decryption Key Length 128"
aesplaintext aesplaintext'
)
aes2key16 = 0x6c3ea0477630ce21a2ce334aa746c2cd :: Word128
aes2iv16 = 0xc782dc4c098c66cbd9cd27d825682c81 :: Word128
aes2plaintext = "This is a 48-byte message (exactly 3 AES blocks)"
aes2ciphertext = [0xd0a02b3836451753d493665d33f0e886,
0x2dea54cdb293abc7506939276772f8d5,
0x021c19216bad525c8579695d83ba2684] :: [Word128]
aes2ciphertext' =
cbc AES.encrypt aes2iv16 aes2key16 $
pkcs5 $
map (fromIntegral . ord) aes2plaintext
aescbcTest3 =
TestCase (
assertEqual "AES CBC PKCS5 3 Blocks Key Length 128"
aes2ciphertext (take 3 aes2ciphertext')
)
-- Comparision with resuts from
-- http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
aes3key24 =
0x8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b :: Word192
aes3iv16 = 0x000102030405060708090a0b0c0d0e0f :: Word128
aes3plaintext =
[0x6bc1bee22e409f96e93d7e117393172a,
0xae2d8a571e03ac9c9eb76fac45af8e51,
0x30c81c46a35ce411e5fbc1191a0a52ef,
0xf69f2445df4f9b17ad2b417be66c3710] :: [Word128]
aes3ciphertext' =
cbc AES.encrypt aes3iv16 aes3key24 $
pkcs5 $
concat $
map (toOctets 256) aes3plaintext
aes3ciphertext =
[0x4f021db243bc633d7178183a9fa071e8,
0xb4d9ada9ad7dedf4e5e738763f69145a,
0x571b242012fb7ae07fa9baac3df102e0,
0x08b0e27988598881d920a9e64f5615cd] :: [Word128]
aescbcTest4 =
TestCase (
assertEqual "AES CBC PKCS5 4 Blocks Key Length 192"
aes3ciphertext (take 4 aes3ciphertext')
)
aes4key32 =
0x603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4
:: Word256
aes4iv16 = 0x000102030405060708090a0b0c0d0e0f :: Word128
aes4plaintext =
[0x6bc1bee22e409f96e93d7e117393172a,
0xae2d8a571e03ac9c9eb76fac45af8e51,
0x30c81c46a35ce411e5fbc1191a0a52ef,
0xf69f2445df4f9b17ad2b417be66c3710] :: [Word128]
aes4ciphertext' =
cbc AES.encrypt aes4iv16 aes4key32 $
pkcs5 $
concat $
map (toOctets 256) aes3plaintext
aes4ciphertext =
[0xf58c4c04d6e5f1ba779eabfb5f7bfbd6,
0x9cfc4e967edb808d679f777bc6702c7d,
0x39f23369a9d9bacfa530e26304231461,
0xb2eb05e2c39be9fcda6c19078c6a9d1b] :: [Word128]
aescbcTest5 =
TestCase (
assertEqual "AES CBC PKCS5 4 Blocks Key Length 256"
aes4ciphertext (take 4 aes4ciphertext')
)
-- Blowfish Tests.
-- Tests from http://www.counterpane.com/vectors.txt.
d = 0xFEDCBA9876543210 :: Word64
k = 0xF0 :: Word8
e = 0xF9AD597C49DB005E :: Word64
e' = Blowfish.encrypt k d
bfTest1 =
TestCase (
assertEqual "Blowfish Key Length 8" e e'
)
k2 = 0xF0E1 :: Word16
e2 = 0xE91D21C1D961A6D6 :: Word64
e2' = Blowfish.encrypt k2 d
bfTest2 =
TestCase (
assertEqual "Blowfish Key Length 16" e2 e2'
)
e8 = 0xE87A244E2CC85E82 :: Word64
k8 = 0xF0E1D2C3B4A59687 :: Word64
e8' = Blowfish.encrypt k8 d
bfTest3 =
TestCase (
assertEqual "Blowfish Key Length 64" e8 e8'
)
e16 = 0x93142887EE3BE15C :: Word64
k16= 0xF0E1D2C3B4A5968778695A4B3C2D1E0F :: Word128
e16' = Blowfish.encrypt k16 d
bfTest4 =
TestCase (
assertEqual "Blowfish Key Length 128" e16 e16'
)
-- Blowfish test with Cipher Block Chaining.
-- Set up the published key, initialization vector and data.
key16 = 0x0123456789ABCDEFF0E1D2C3B4A59687 :: Word128
iv8 = 0xFEDCBA9876543210 :: Word64
data29 = "7654321 Now is the time for \NUL"
-- Pad with nulls as in the example.
e29' =
cbc Blowfish.encrypt iv8 key16 $ padNulls $ map (fromIntegral . ord) data29
e29 = [0x6B,0x77,0xB4,0xD6,0x30,0x06,0xDE,0xE6,
0x05,0xB1,0x56,0xE2,0x74,0x03,0x97,0x93,
0x58,0xDE,0xB9,0xE7,0x15,0x46,0x16,0xD9,
0x59,0xF1,0x65,0x2B,0xD5,0xFF,0x92,0xCC] :: [Octet]
bfTest5 =
TestCase (
assertEqual "AES CBC Nulls Key Length 128"
e29 (concat $ map (toOctets 256) e29')
)
-- DES Tests
-- Test from http://www.itl.nist.gov/fipspubs/fip81.htm
key = 0x0123456789abcdef :: Word64
iv = 0x1234567890abcdef :: Word64
expectedDES = [0xe5c7cdde872bf27c,
0x43e934008c389c0f,
0x683788499a7c05f6] :: [Word64]
plainText = "Now is the time for all "
-- Pad using PKCS#5 so only take the first 3 blocks of the ciphertext.
cipherText =
cbc DES.encrypt iv key $ pkcs5 $ map (fromIntegral . ord) plainText
descbcTest1 =
TestCase (
assertEqual "DES CBC PKCS5 3 Blocks"
expectedDES (take 3 cipherText)
)
tests =
TestList [
aesTest1, aesTest2, aesTest3, aescbcTest1,
aescbcTest2, aescbcTest3, aescbcTest4, aescbcTest5,
bfTest1, bfTest2, bfTest3, bfTest4, bfTest5,
descbcTest1
]
main = runTestTT tests