1 /*******************************************************************************
2 
3     libgcrypt with algorithm AES (Rijndael) with a 128 bit key.
4 
5     Requires linking with libgcrypt:
6             -L -lgcrypt
7 
8     See_Also:
9         http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
10 
11     Copyright:
12         Copyright (c) 2009-2016 dunnhumby Germany GmbH.
13         All rights reserved.
14 
15     License:
16         Boost Software License Version 1.0. See LICENSE_BOOST.txt for details.
17         Alternatively, this file may be distributed under the terms of the Tango
18         3-Clause BSD License (see LICENSE_BSD.txt for details).
19 
20 *******************************************************************************/
21 
22 module ocean.util.cipher.gcrypt.AES;
23 
24 import ocean.meta.types.Qualifiers;
25 import ocean.util.cipher.gcrypt.core.Gcrypt;
26 
27 
28 /*******************************************************************************
29 
30     Gcrypt with AES with mode ECB.
31 
32     See usage example in unittest below.
33 
34 *******************************************************************************/
35 
36 public alias GcryptNoIV!(Algorithm.GCRY_CIPHER_AES, Mode.GCRY_CIPHER_MODE_ECB) AES128;
37 
38 /// Usage example of AES with 128-bit keys
39 unittest
40 {
41     // AES128 requires a key of length 16 bytes.
42     static immutable KEY = "asdfghjklqwertyu";
43 
44     testAES!(AES128, KEY)();
45 }
46 
47 public alias GcryptNoIV!(Algorithm.GCRY_CIPHER_AES192, Mode.GCRY_CIPHER_MODE_ECB) AES192;
48 
49 /// Usage example of AES with 192-bit keys
50 unittest
51 {
52     // AES192 requires a key of length 24 bytes.
53     static immutable KEY = "abcdefghijklmnopqrstuvwx";
54 
55     testAES!(AES192, KEY);
56 }
57 
58 public alias GcryptNoIV!(Algorithm.GCRY_CIPHER_AES256, Mode.GCRY_CIPHER_MODE_ECB) AES256;
59 
60 /// Usage example of AES with 256-bit keys
61 unittest
62 {
63     // AES256 requires a key of length 32 bytes.
64     static immutable KEY = "abcdefghijklmnopqrstuvwxyz012345";
65 
66     testAES!(AES256, KEY);
67 }
68 
69 /*******************************************************************************
70 
71     Gcrypt with AES with mode CBC.
72 
73     See usage example in unittest below.
74 
75 *******************************************************************************/
76 
77 public alias GcryptWithIV!(Algorithm.GCRY_CIPHER_AES, Mode.GCRY_CIPHER_MODE_CBC) AES128_CBC;
78 
79 /// Usage example of AES-CBC with 128-bit keys
80 unittest
81 {
82     // AES128-CBC requires a key of length 16 bytes.
83     static immutable KEY = "asdfghjklqwertyu";
84 
85     // AES128-CBC requires an IV of length 16 bytes.
86     static immutable IV = "0123456789ABCDEF";
87 
88     testAES_IV!(AES128_CBC, KEY, IV);
89 }
90 
91 public alias GcryptWithIV!(Algorithm.GCRY_CIPHER_AES192, Mode.GCRY_CIPHER_MODE_CBC) AES192_CBC;
92 
93 /// Usage example of AES-CBC with 192-bit keys
94 unittest
95 {
96     // AES192-CBC requires a key of length 24 bytes.
97     static immutable KEY = "abcdefghijklmnopqrstuvwx";
98 
99     // AES192-CBC requires an IV of length 16 bytes.
100     static immutable IV = "0123456789ABCDEF";
101 
102     testAES_IV!(AES192_CBC, KEY, IV);
103 }
104 
105 public alias GcryptWithIV!(Algorithm.GCRY_CIPHER_AES256, Mode.GCRY_CIPHER_MODE_CBC) AES256_CBC;
106 
107 /// Usage example of AES-CBC with 256-bit keys
108 unittest
109 {
110     // AES256-CBC requires a key of length 32 bytes.
111     static immutable KEY = "abcdefghijklmnopqrstuvwxyz012345";
112 
113     // AES256-CBC requires an IV of length 16 bytes.
114     static immutable IV = "0123456789ABCDEF";
115 
116     testAES_IV!(AES256_CBC, KEY, IV);
117 }
118 
119 version (unittest)
120 {
121     import ocean.core.Test;
122 
123     void testAES ( Cipher, istring str_key ) ( )
124     {
125         auto key = cast(immutable(ubyte)[])str_key;
126 
127         // Test that only keys of the provided length are allowed
128         Cipher.testFixedKeyLength(key);
129 
130         // AES operates on 16-byte blocks.
131         istring text = "Length divide 16";
132         mstring encrypted_text, decrypted_text;
133 
134         // Create the class.
135         auto cipher = new Cipher(key);
136 
137         // encryption/decryption is done in place so first copy the plain text
138         // to a buffer.
139         encrypted_text ~= text;
140 
141         // The actual encryption
142         cipher.encrypt(encrypted_text);
143 
144         // Since decryption is done in place we copy the decrypted string to a
145         // new buffer.
146         decrypted_text ~= encrypted_text;
147 
148         // The decryption call.
149         cipher.decrypt(decrypted_text);
150 
151         // We have now successfully encrypted and decrypted a string.
152         test!("==")(text, decrypted_text);
153     }
154 
155     void testAES_IV ( Cipher, istring str_key, istring str_iv ) ( )
156     {
157         auto key = cast(immutable(ubyte)[])str_key;
158         auto iv = cast(immutable(ubyte)[])str_iv;
159 
160         // Test that only keys of the provided length are allowed
161         Cipher.testFixedKeyLength(key);
162 
163         // AES operates on 16-byte blocks;
164         istring text = "Length divide 16";
165         mstring encrypted_text, decrypted_text;
166 
167         // Create the class.
168         auto cipher = new Cipher(key);
169 
170         // encryption/decryption is done in place so first copy the plain text
171         // to a buffer
172         encrypted_text ~= text;
173 
174         // The actual encryption
175         cipher.encrypt(encrypted_text, iv);
176 
177         // Since decryption is done in place we copy the decrypted string to a
178         // new buffer.
179         decrypted_text ~= encrypted_text;
180 
181         // The decryption call.
182         cipher.decrypt(decrypted_text, iv);
183 
184         // We have now successfully encrypted and decrypted a string.
185         test!("==")(text, decrypted_text);
186     }
187 }