]> gitweb.factorcode.org Git - factor.git/commitdiff
Initial commit of lookup-table AES implementation
authorFred Alger <fred@fredalger.net>
Sun, 16 Jun 2013 17:09:39 +0000 (13:09 -0400)
committerDoug Coleman <doug.coleman@gmail.com>
Sat, 11 Jan 2014 19:10:47 +0000 (11:10 -0800)
In need of optimization and cleanup.  Uses 32-bit integers arithmetic
and seems to run very quickly (100k key expansions + encrypts in 3.88
= 400K/s encryption).  Based on p7zip's optimized C implementation.

extra/crypto/aes/aes-tests.factor
extra/crypto/aes/aes.factor
extra/crypto/aes/authors.txt
extra/crypto/aes/utils/utils.factor [new file with mode: 0644]

index b1fda38f251710269706ab223b13c90383c8d6d1..5c9f78de0c624a7a44895c0f4fd43cd0d81fef32 100644 (file)
 ! Copyright (C) 2008 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel sequences grouping tools.test crypto.aes ;
+USING: accessors byte-arrays.hex crypto.aes crypto.aes.utils
+grouping kernel sequences tools.test ;
 IN: crypto.aes.tests
 
+#! fips-197 test vectors
+CONSTANT: plaintext HEX{ 32 43 f6 a8 88 5a 30 8d 31 31 98 a2 e0 37 07 34 }
+CONSTANT: key HEX{ 2b 7e 15 16 28 ae d2 a6 ab f7 15 88 09 cf 4f 3c }
+
 [ {
         0x00 0x01 0x02 0x04 0x08 0x10
         0x20 0x40 0x80 0x1b 0x36
 } ] [ rcon ] unit-test
 
+
 [ {
-    0x63 0x7c 0x77 0x7b 0xf2 0x6b 0x6f 0xc5
-    0x30 0x01 0x67 0x2b 0xfe 0xd7 0xab 0x76
-    0xca 0x82 0xc9 0x7d 0xfa 0x59 0x47 0xf0
-    0xad 0xd4 0xa2 0xaf 0x9c 0xa4 0x72 0xc0
-    0xb7 0xfd 0x93 0x26 0x36 0x3f 0xf7 0xcc
-    0x34 0xa5 0xe5 0xf1 0x71 0xd8 0x31 0x15
-    0x04 0xc7 0x23 0xc3 0x18 0x96 0x05 0x9a
-    0x07 0x12 0x80 0xe2 0xeb 0x27 0xb2 0x75
-    0x09 0x83 0x2c 0x1a 0x1b 0x6e 0x5a 0xa0
-    0x52 0x3b 0xd6 0xb3 0x29 0xe3 0x2f 0x84
-    0x53 0xd1 0x00 0xed 0x20 0xfc 0xb1 0x5b
-    0x6a 0xcb 0xbe 0x39 0x4a 0x4c 0x58 0xcf
-    0xd0 0xef 0xaa 0xfb 0x43 0x4d 0x33 0x85
-    0x45 0xf9 0x02 0x7f 0x50 0x3c 0x9f 0xa8
-    0x51 0xa3 0x40 0x8f 0x92 0x9d 0x38 0xf5
-    0xbc 0xb6 0xda 0x21 0x10 0xff 0xf3 0xd2
-    0xcd 0x0c 0x13 0xec 0x5f 0x97 0x44 0x17
-    0xc4 0xa7 0x7e 0x3d 0x64 0x5d 0x19 0x73
-    0x60 0x81 0x4f 0xdc 0x22 0x2a 0x90 0x88
-    0x46 0xee 0xb8 0x14 0xde 0x5e 0x0b 0xdb
-    0xe0 0x32 0x3a 0x0a 0x49 0x06 0x24 0x5c
-    0xc2 0xd3 0xac 0x62 0x91 0x95 0xe4 0x79
-    0xe7 0xc8 0x37 0x6d 0x8d 0xd5 0x4e 0xa9
-    0x6c 0x56 0xf4 0xea 0x65 0x7a 0xae 0x08
-    0xba 0x78 0x25 0x2e 0x1c 0xa6 0xb4 0xc6
-    0xe8 0xdd 0x74 0x1f 0x4b 0xbd 0x8b 0x8a
-    0x70 0x3e 0xb5 0x66 0x48 0x03 0xf6 0x0e
-    0x61 0x35 0x57 0xb9 0x86 0xc1 0x1d 0x9e
-    0xe1 0xf8 0x98 0x11 0x69 0xd9 0x8e 0x94
-    0x9b 0x1e 0x87 0xe9 0xce 0x55 0x28 0xdf
-    0x8c 0xa1 0x89 0x0d 0xbf 0xe6 0x42 0x68
-    0x41 0x99 0x2d 0x0f 0xb0 0x54 0xbb 0x16
-} ] [ sbox ] unit-test
+    0xc66363a5 0xf87c7c84 0xee777799 0xf67b7b8d 0xfff2f20d 0xd66b6bbd 0xde6f6fb1 0x91c5c554
+    0x60303050 0x02010103 0xce6767a9 0x562b2b7d 0xe7fefe19 0xb5d7d762 0x4dababe6 0xec76769a
+    0x8fcaca45 0x1f82829d 0x89c9c940 0xfa7d7d87 0xeffafa15 0xb25959eb 0x8e4747c9 0xfbf0f00b
+    0x41adadec 0xb3d4d467 0x5fa2a2fd 0x45afafea 0x239c9cbf 0x53a4a4f7 0xe4727296 0x9bc0c05b
+    0x75b7b7c2 0xe1fdfd1c 0x3d9393ae 0x4c26266a 0x6c36365a 0x7e3f3f41 0xf5f7f702 0x83cccc4f
+    0x6834345c 0x51a5a5f4 0xd1e5e534 0xf9f1f108 0xe2717193 0xabd8d873 0x62313153 0x2a15153f
+    0x0804040c 0x95c7c752 0x46232365 0x9dc3c35e 0x30181828 0x379696a1 0x0a05050f 0x2f9a9ab5
+    0x0e070709 0x24121236 0x1b80809b 0xdfe2e23d 0xcdebeb26 0x4e272769 0x7fb2b2cd 0xea75759f
+    0x1209091b 0x1d83839e 0x582c2c74 0x341a1a2e 0x361b1b2d 0xdc6e6eb2 0xb45a5aee 0x5ba0a0fb
+    0xa45252f6 0x763b3b4d 0xb7d6d661 0x7db3b3ce 0x5229297b 0xdde3e33e 0x5e2f2f71 0x13848497
+    0xa65353f5 0xb9d1d168 0x00000000 0xc1eded2c 0x40202060 0xe3fcfc1f 0x79b1b1c8 0xb65b5bed
+    0xd46a6abe 0x8dcbcb46 0x67bebed9 0x7239394b 0x944a4ade 0x984c4cd4 0xb05858e8 0x85cfcf4a
+    0xbbd0d06b 0xc5efef2a 0x4faaaae5 0xedfbfb16 0x864343c5 0x9a4d4dd7 0x66333355 0x11858594
+    0x8a4545cf 0xe9f9f910 0x04020206 0xfe7f7f81 0xa05050f0 0x783c3c44 0x259f9fba 0x4ba8a8e3
+    0xa25151f3 0x5da3a3fe 0x804040c0 0x058f8f8a 0x3f9292ad 0x219d9dbc 0x70383848 0xf1f5f504
+    0x63bcbcdf 0x77b6b6c1 0xafdada75 0x42212163 0x20101030 0xe5ffff1a 0xfdf3f30e 0xbfd2d26d
+    0x81cdcd4c 0x180c0c14 0x26131335 0xc3ecec2f 0xbe5f5fe1 0x359797a2 0x884444cc 0x2e171739
+    0x93c4c457 0x55a7a7f2 0xfc7e7e82 0x7a3d3d47 0xc86464ac 0xba5d5de7 0x3219192b 0xe6737395
+    0xc06060a0 0x19818198 0x9e4f4fd1 0xa3dcdc7f 0x44222266 0x542a2a7e 0x3b9090ab 0x0b888883
+    0x8c4646ca 0xc7eeee29 0x6bb8b8d3 0x2814143c 0xa7dede79 0xbc5e5ee2 0x160b0b1d 0xaddbdb76
+    0xdbe0e03b 0x64323256 0x743a3a4e 0x140a0a1e 0x924949db 0x0c06060a 0x4824246c 0xb85c5ce4
+    0x9fc2c25d 0xbdd3d36e 0x43acacef 0xc46262a6 0x399191a8 0x319595a4 0xd3e4e437 0xf279798b
+    0xd5e7e732 0x8bc8c843 0x6e373759 0xda6d6db7 0x018d8d8c 0xb1d5d564 0x9c4e4ed2 0x49a9a9e0
+    0xd86c6cb4 0xac5656fa 0xf3f4f407 0xcfeaea25 0xca6565af 0xf47a7a8e 0x47aeaee9 0x10080818
+    0x6fbabad5 0xf0787888 0x4a25256f 0x5c2e2e72 0x381c1c24 0x57a6a6f1 0x73b4b4c7 0x97c6c651
+    0xcbe8e823 0xa1dddd7c 0xe874749c 0x3e1f1f21 0x964b4bdd 0x61bdbddc 0x0d8b8b86 0x0f8a8a85
+    0xe0707090 0x7c3e3e42 0x71b5b5c4 0xcc6666aa 0x904848d8 0x06030305 0xf7f6f601 0x1c0e0e12
+    0xc26161a3 0x6a35355f 0xae5757f9 0x69b9b9d0 0x17868691 0x99c1c158 0x3a1d1d27 0x279e9eb9
+    0xd9e1e138 0xebf8f813 0x2b9898b3 0x22111133 0xd26969bb 0xa9d9d970 0x078e8e89 0x339494a7
+    0x2d9b9bb6 0x3c1e1e22 0x15878792 0xc9e9e920 0x87cece49 0xaa5555ff 0x50282878 0xa5dfdf7a
+    0x038c8c8f 0x59a1a1f8 0x09898980 0x1a0d0d17 0x65bfbfda 0xd7e6e631 0x844242c6 0xd06868b8
+    0x824141c3 0x299999b0 0x5a2d2d77 0x1e0f0f11 0x7bb0b0cb 0xa85454fc 0x6dbbbbd6 0x2c16163a
+    0xa5c66363 0x84f87c7c 0x99ee7777 0x8df67b7b 0x0dfff2f2 0xbdd66b6b 0xb1de6f6f 0x5491c5c5
+    0x50603030 0x03020101 0xa9ce6767 0x7d562b2b 0x19e7fefe 0x62b5d7d7 0xe64dabab 0x9aec7676
+    0x458fcaca 0x9d1f8282 0x4089c9c9 0x87fa7d7d 0x15effafa 0xebb25959 0xc98e4747 0x0bfbf0f0
+    0xec41adad 0x67b3d4d4 0xfd5fa2a2 0xea45afaf 0xbf239c9c 0xf753a4a4 0x96e47272 0x5b9bc0c0
+    0xc275b7b7 0x1ce1fdfd 0xae3d9393 0x6a4c2626 0x5a6c3636 0x417e3f3f 0x02f5f7f7 0x4f83cccc
+    0x5c683434 0xf451a5a5 0x34d1e5e5 0x08f9f1f1 0x93e27171 0x73abd8d8 0x53623131 0x3f2a1515
+    0x0c080404 0x5295c7c7 0x65462323 0x5e9dc3c3 0x28301818 0xa1379696 0x0f0a0505 0xb52f9a9a
+    0x090e0707 0x36241212 0x9b1b8080 0x3ddfe2e2 0x26cdebeb 0x694e2727 0xcd7fb2b2 0x9fea7575
+    0x1b120909 0x9e1d8383 0x74582c2c 0x2e341a1a 0x2d361b1b 0xb2dc6e6e 0xeeb45a5a 0xfb5ba0a0
+    0xf6a45252 0x4d763b3b 0x61b7d6d6 0xce7db3b3 0x7b522929 0x3edde3e3 0x715e2f2f 0x97138484
+    0xf5a65353 0x68b9d1d1 0x00000000 0x2cc1eded 0x60402020 0x1fe3fcfc 0xc879b1b1 0xedb65b5b
+    0xbed46a6a 0x468dcbcb 0xd967bebe 0x4b723939 0xde944a4a 0xd4984c4c 0xe8b05858 0x4a85cfcf
+    0x6bbbd0d0 0x2ac5efef 0xe54faaaa 0x16edfbfb 0xc5864343 0xd79a4d4d 0x55663333 0x94118585
+    0xcf8a4545 0x10e9f9f9 0x06040202 0x81fe7f7f 0xf0a05050 0x44783c3c 0xba259f9f 0xe34ba8a8
+    0xf3a25151 0xfe5da3a3 0xc0804040 0x8a058f8f 0xad3f9292 0xbc219d9d 0x48703838 0x04f1f5f5
+    0xdf63bcbc 0xc177b6b6 0x75afdada 0x63422121 0x30201010 0x1ae5ffff 0x0efdf3f3 0x6dbfd2d2
+    0x4c81cdcd 0x14180c0c 0x35261313 0x2fc3ecec 0xe1be5f5f 0xa2359797 0xcc884444 0x392e1717
+    0x5793c4c4 0xf255a7a7 0x82fc7e7e 0x477a3d3d 0xacc86464 0xe7ba5d5d 0x2b321919 0x95e67373
+    0xa0c06060 0x98198181 0xd19e4f4f 0x7fa3dcdc 0x66442222 0x7e542a2a 0xab3b9090 0x830b8888
+    0xca8c4646 0x29c7eeee 0xd36bb8b8 0x3c281414 0x79a7dede 0xe2bc5e5e 0x1d160b0b 0x76addbdb
+    0x3bdbe0e0 0x56643232 0x4e743a3a 0x1e140a0a 0xdb924949 0x0a0c0606 0x6c482424 0xe4b85c5c
+    0x5d9fc2c2 0x6ebdd3d3 0xef43acac 0xa6c46262 0xa8399191 0xa4319595 0x37d3e4e4 0x8bf27979
+    0x32d5e7e7 0x438bc8c8 0x596e3737 0xb7da6d6d 0x8c018d8d 0x64b1d5d5 0xd29c4e4e 0xe049a9a9
+    0xb4d86c6c 0xfaac5656 0x07f3f4f4 0x25cfeaea 0xafca6565 0x8ef47a7a 0xe947aeae 0x18100808
+    0xd56fbaba 0x88f07878 0x6f4a2525 0x725c2e2e 0x24381c1c 0xf157a6a6 0xc773b4b4 0x5197c6c6
+    0x23cbe8e8 0x7ca1dddd 0x9ce87474 0x213e1f1f 0xdd964b4b 0xdc61bdbd 0x860d8b8b 0x850f8a8a
+    0x90e07070 0x427c3e3e 0xc471b5b5 0xaacc6666 0xd8904848 0x05060303 0x01f7f6f6 0x121c0e0e
+    0xa3c26161 0x5f6a3535 0xf9ae5757 0xd069b9b9 0x91178686 0x5899c1c1 0x273a1d1d 0xb9279e9e
+    0x38d9e1e1 0x13ebf8f8 0xb32b9898 0x33221111 0xbbd26969 0x70a9d9d9 0x89078e8e 0xa7339494
+    0xb62d9b9b 0x223c1e1e 0x92158787 0x20c9e9e9 0x4987cece 0xffaa5555 0x78502828 0x7aa5dfdf
+    0x8f038c8c 0xf859a1a1 0x80098989 0x171a0d0d 0xda65bfbf 0x31d7e6e6 0xc6844242 0xb8d06868
+    0xc3824141 0xb0299999 0x775a2d2d 0x111e0f0f 0xcb7bb0b0 0xfca85454 0xd66dbbbb 0x3a2c1616
+    0x63a5c663 0x7c84f87c 0x7799ee77 0x7b8df67b 0xf20dfff2 0x6bbdd66b 0x6fb1de6f 0xc55491c5
+    0x30506030 0x01030201 0x67a9ce67 0x2b7d562b 0xfe19e7fe 0xd762b5d7 0xabe64dab 0x769aec76
+    0xca458fca 0x829d1f82 0xc94089c9 0x7d87fa7d 0xfa15effa 0x59ebb259 0x47c98e47 0xf00bfbf0
+    0xadec41ad 0xd467b3d4 0xa2fd5fa2 0xafea45af 0x9cbf239c 0xa4f753a4 0x7296e472 0xc05b9bc0
+    0xb7c275b7 0xfd1ce1fd 0x93ae3d93 0x266a4c26 0x365a6c36 0x3f417e3f 0xf702f5f7 0xcc4f83cc
+    0x345c6834 0xa5f451a5 0xe534d1e5 0xf108f9f1 0x7193e271 0xd873abd8 0x31536231 0x153f2a15
+    0x040c0804 0xc75295c7 0x23654623 0xc35e9dc3 0x18283018 0x96a13796 0x050f0a05 0x9ab52f9a
+    0x07090e07 0x12362412 0x809b1b80 0xe23ddfe2 0xeb26cdeb 0x27694e27 0xb2cd7fb2 0x759fea75
+    0x091b1209 0x839e1d83 0x2c74582c 0x1a2e341a 0x1b2d361b 0x6eb2dc6e 0x5aeeb45a 0xa0fb5ba0
+    0x52f6a452 0x3b4d763b 0xd661b7d6 0xb3ce7db3 0x297b5229 0xe33edde3 0x2f715e2f 0x84971384
+    0x53f5a653 0xd168b9d1 0x00000000 0xed2cc1ed 0x20604020 0xfc1fe3fc 0xb1c879b1 0x5bedb65b
+    0x6abed46a 0xcb468dcb 0xbed967be 0x394b7239 0x4ade944a 0x4cd4984c 0x58e8b058 0xcf4a85cf
+    0xd06bbbd0 0xef2ac5ef 0xaae54faa 0xfb16edfb 0x43c58643 0x4dd79a4d 0x33556633 0x85941185
+    0x45cf8a45 0xf910e9f9 0x02060402 0x7f81fe7f 0x50f0a050 0x3c44783c 0x9fba259f 0xa8e34ba8
+    0x51f3a251 0xa3fe5da3 0x40c08040 0x8f8a058f 0x92ad3f92 0x9dbc219d 0x38487038 0xf504f1f5
+    0xbcdf63bc 0xb6c177b6 0xda75afda 0x21634221 0x10302010 0xff1ae5ff 0xf30efdf3 0xd26dbfd2
+    0xcd4c81cd 0x0c14180c 0x13352613 0xec2fc3ec 0x5fe1be5f 0x97a23597 0x44cc8844 0x17392e17
+    0xc45793c4 0xa7f255a7 0x7e82fc7e 0x3d477a3d 0x64acc864 0x5de7ba5d 0x192b3219 0x7395e673
+    0x60a0c060 0x81981981 0x4fd19e4f 0xdc7fa3dc 0x22664422 0x2a7e542a 0x90ab3b90 0x88830b88
+    0x46ca8c46 0xee29c7ee 0xb8d36bb8 0x143c2814 0xde79a7de 0x5ee2bc5e 0x0b1d160b 0xdb76addb
+    0xe03bdbe0 0x32566432 0x3a4e743a 0x0a1e140a 0x49db9249 0x060a0c06 0x246c4824 0x5ce4b85c
+    0xc25d9fc2 0xd36ebdd3 0xacef43ac 0x62a6c462 0x91a83991 0x95a43195 0xe437d3e4 0x798bf279
+    0xe732d5e7 0xc8438bc8 0x37596e37 0x6db7da6d 0x8d8c018d 0xd564b1d5 0x4ed29c4e 0xa9e049a9
+    0x6cb4d86c 0x56faac56 0xf407f3f4 0xea25cfea 0x65afca65 0x7a8ef47a 0xaee947ae 0x08181008
+    0xbad56fba 0x7888f078 0x256f4a25 0x2e725c2e 0x1c24381c 0xa6f157a6 0xb4c773b4 0xc65197c6
+    0xe823cbe8 0xdd7ca1dd 0x749ce874 0x1f213e1f 0x4bdd964b 0xbddc61bd 0x8b860d8b 0x8a850f8a
+    0x7090e070 0x3e427c3e 0xb5c471b5 0x66aacc66 0x48d89048 0x03050603 0xf601f7f6 0x0e121c0e
+    0x61a3c261 0x355f6a35 0x57f9ae57 0xb9d069b9 0x86911786 0xc15899c1 0x1d273a1d 0x9eb9279e
+    0xe138d9e1 0xf813ebf8 0x98b32b98 0x11332211 0x69bbd269 0xd970a9d9 0x8e89078e 0x94a73394
+    0x9bb62d9b 0x1e223c1e 0x87921587 0xe920c9e9 0xce4987ce 0x55ffaa55 0x28785028 0xdf7aa5df
+    0x8c8f038c 0xa1f859a1 0x89800989 0x0d171a0d 0xbfda65bf 0xe631d7e6 0x42c68442 0x68b8d068
+    0x41c38241 0x99b02999 0x2d775a2d 0x0f111e0f 0xb0cb7bb0 0x54fca854 0xbbd66dbb 0x163a2c16
+    0x6363a5c6 0x7c7c84f8 0x777799ee 0x7b7b8df6 0xf2f20dff 0x6b6bbdd6 0x6f6fb1de 0xc5c55491
+    0x30305060 0x01010302 0x6767a9ce 0x2b2b7d56 0xfefe19e7 0xd7d762b5 0xababe64d 0x76769aec
+    0xcaca458f 0x82829d1f 0xc9c94089 0x7d7d87fa 0xfafa15ef 0x5959ebb2 0x4747c98e 0xf0f00bfb
+    0xadadec41 0xd4d467b3 0xa2a2fd5f 0xafafea45 0x9c9cbf23 0xa4a4f753 0x727296e4 0xc0c05b9b
+    0xb7b7c275 0xfdfd1ce1 0x9393ae3d 0x26266a4c 0x36365a6c 0x3f3f417e 0xf7f702f5 0xcccc4f83
+    0x34345c68 0xa5a5f451 0xe5e534d1 0xf1f108f9 0x717193e2 0xd8d873ab 0x31315362 0x15153f2a
+    0x04040c08 0xc7c75295 0x23236546 0xc3c35e9d 0x18182830 0x9696a137 0x05050f0a 0x9a9ab52f
+    0x0707090e 0x12123624 0x80809b1b 0xe2e23ddf 0xebeb26cd 0x2727694e 0xb2b2cd7f 0x75759fea
+    0x09091b12 0x83839e1d 0x2c2c7458 0x1a1a2e34 0x1b1b2d36 0x6e6eb2dc 0x5a5aeeb4 0xa0a0fb5b
+    0x5252f6a4 0x3b3b4d76 0xd6d661b7 0xb3b3ce7d 0x29297b52 0xe3e33edd 0x2f2f715e 0x84849713
+    0x5353f5a6 0xd1d168b9 0x00000000 0xeded2cc1 0x20206040 0xfcfc1fe3 0xb1b1c879 0x5b5bedb6
+    0x6a6abed4 0xcbcb468d 0xbebed967 0x39394b72 0x4a4ade94 0x4c4cd498 0x5858e8b0 0xcfcf4a85
+    0xd0d06bbb 0xefef2ac5 0xaaaae54f 0xfbfb16ed 0x4343c586 0x4d4dd79a 0x33335566 0x85859411
+    0x4545cf8a 0xf9f910e9 0x02020604 0x7f7f81fe 0x5050f0a0 0x3c3c4478 0x9f9fba25 0xa8a8e34b
+    0x5151f3a2 0xa3a3fe5d 0x4040c080 0x8f8f8a05 0x9292ad3f 0x9d9dbc21 0x38384870 0xf5f504f1
+    0xbcbcdf63 0xb6b6c177 0xdada75af 0x21216342 0x10103020 0xffff1ae5 0xf3f30efd 0xd2d26dbf
+    0xcdcd4c81 0x0c0c1418 0x13133526 0xecec2fc3 0x5f5fe1be 0x9797a235 0x4444cc88 0x1717392e
+    0xc4c45793 0xa7a7f255 0x7e7e82fc 0x3d3d477a 0x6464acc8 0x5d5de7ba 0x19192b32 0x737395e6
+    0x6060a0c0 0x81819819 0x4f4fd19e 0xdcdc7fa3 0x22226644 0x2a2a7e54 0x9090ab3b 0x8888830b
+    0x4646ca8c 0xeeee29c7 0xb8b8d36b 0x14143c28 0xdede79a7 0x5e5ee2bc 0x0b0b1d16 0xdbdb76ad
+    0xe0e03bdb 0x32325664 0x3a3a4e74 0x0a0a1e14 0x4949db92 0x06060a0c 0x24246c48 0x5c5ce4b8
+    0xc2c25d9f 0xd3d36ebd 0xacacef43 0x6262a6c4 0x9191a839 0x9595a431 0xe4e437d3 0x79798bf2
+    0xe7e732d5 0xc8c8438b 0x3737596e 0x6d6db7da 0x8d8d8c01 0xd5d564b1 0x4e4ed29c 0xa9a9e049
+    0x6c6cb4d8 0x5656faac 0xf4f407f3 0xeaea25cf 0x6565afca 0x7a7a8ef4 0xaeaee947 0x08081810
+    0xbabad56f 0x787888f0 0x25256f4a 0x2e2e725c 0x1c1c2438 0xa6a6f157 0xb4b4c773 0xc6c65197
+    0xe8e823cb 0xdddd7ca1 0x74749ce8 0x1f1f213e 0x4b4bdd96 0xbdbddc61 0x8b8b860d 0x8a8a850f
+    0x707090e0 0x3e3e427c 0xb5b5c471 0x6666aacc 0x4848d890 0x03030506 0xf6f601f7 0x0e0e121c
+    0x6161a3c2 0x35355f6a 0x5757f9ae 0xb9b9d069 0x86869117 0xc1c15899 0x1d1d273a 0x9e9eb927
+    0xe1e138d9 0xf8f813eb 0x9898b32b 0x11113322 0x6969bbd2 0xd9d970a9 0x8e8e8907 0x9494a733
+    0x9b9bb62d 0x1e1e223c 0x87879215 0xe9e920c9 0xcece4987 0x5555ffaa 0x28287850 0xdfdf7aa5
+    0x8c8c8f03 0xa1a1f859 0x89898009 0x0d0d171a 0xbfbfda65 0xe6e631d7 0x4242c684 0x6868b8d0
+    0x4141c382 0x9999b029 0x2d2d775a 0x0f0f111e 0xb0b0cb7b 0x5454fca8 0xbbbbd66d 0x16163a2c
+} ] [ t-table ] unit-test
+
+#! NOT TESTED:
+#! ui32
+#! set-t
+#! set-d
+
+[ { 0x01020304 0x02030401 0x03040102 0x04010203 } ] [
+  { 0x01010101 0x02020202 0x03030303 0x04040404 } shift-rows
+] unit-test
+
+[ { 0x01010101 0x02020202 0x03030303 0x04040404 } ] [
+ { 0x01020304 0x02030401 0x03040102 0x04010203 }  unshift-rows
+] unit-test
+
+[ 0x02030401 ] [ 0x01020304 rotword ] unit-test
 
 [
-{
-    0x52 0x09 0x6a 0xd5 0x30 0x36 0xa5 0x38 
-    0xbf 0x40 0xa3 0x9e 0x81 0xf3 0xd7 0xfb 
-    0x7c 0xe3 0x39 0x82 0x9b 0x2f 0xff 0x87 
-    0x34 0x8e 0x43 0x44 0xc4 0xde 0xe9 0xcb 
-    0x54 0x7b 0x94 0x32 0xa6 0xc2 0x23 0x3d 
-    0xee 0x4c 0x95 0x0b 0x42 0xfa 0xc3 0x4e 
-    0x08 0x2e 0xa1 0x66 0x28 0xd9 0x24 0xb2 
-    0x76 0x5b 0xa2 0x49 0x6d 0x8b 0xd1 0x25 
-    0x72 0xf8 0xf6 0x64 0x86 0x68 0x98 0x16 
-    0xd4 0xa4 0x5c 0xcc 0x5d 0x65 0xb6 0x92 
-    0x6c 0x70 0x48 0x50 0xfd 0xed 0xb9 0xda 
-    0x5e 0x15 0x46 0x57 0xa7 0x8d 0x9d 0x84 
-    0x90 0xd8 0xab 0x00 0x8c 0xbc 0xd3 0x0a 
-    0xf7 0xe4 0x58 0x05 0xb8 0xb3 0x45 0x06 
-    0xd0 0x2c 0x1e 0x8f 0xca 0x3f 0x0f 0x02 
-    0xc1 0xaf 0xbd 0x03 0x01 0x13 0x8a 0x6b 
-    0x3a 0x91 0x11 0x41 0x4f 0x67 0xdc 0xea 
-    0x97 0xf2 0xcf 0xce 0xf0 0xb4 0xe6 0x73 
-    0x96 0xac 0x74 0x22 0xe7 0xad 0x35 0x85 
-    0xe2 0xf9 0x37 0xe8 0x1c 0x75 0xdf 0x6e 
-    0x47 0xf1 0x1a 0x71 0x1d 0x29 0xc5 0x89 
-    0x6f 0xb7 0x62 0x0e 0xaa 0x18 0xbe 0x1b 
-    0xfc 0x56 0x3e 0x4b 0xc6 0xd2 0x79 0x20 
-    0x9a 0xdb 0xc0 0xfe 0x78 0xcd 0x5a 0xf4 
-    0x1f 0xdd 0xa8 0x33 0x88 0x07 0xc7 0x31 
-    0xb1 0x12 0x10 0x59 0x27 0x80 0xec 0x5f 
-    0x60 0x51 0x7f 0xa9 0x19 0xb5 0x4a 0x0d 
-    0x2d 0xe5 0x7a 0x9f 0x93 0xc9 0x9c 0xef 
-    0xa0 0xe0 0x3b 0x4d 0xae 0x2a 0xf5 0xb0 
-    0xc8 0xeb 0xbb 0x3c 0x83 0x53 0x99 0x61 
-    0x17 0x2b 0x04 0x7e 0xba 0x77 0xd6 0x26 
-    0xe1 0x69 0x14 0x63 0x55 0x21 0x0c 0x7d 
-}
-] [ inv-sbox ] unit-test
+V{ 729683222 682545830 2885096840 164581180 2700803607 2287217841
+   597899577 711751173 4072838642 2056698179 1496678522 1935275647
+   1031817085 1192689214 505642564 1836746811 4014253377 2823969663
+   3060868411 3674975488 3570517752 2089000327 3404904636 301536700
+   1837671290 285949693 3690563137 3389035517 1314191118 1600113139
+   2225491890 1319558223 3939660577 3045964498 824964448 2139957551
+   2893506291 435870753 684796225 1465647214 3491035560 3387827593
+   3779005640 3059944614 }
+] [
+  HEX{ 2b 7e 15 16 28 ae d2 a6 ab f7 15 88 09 cf 4f 3c } #! AES-128 key expansion test vector from FIPS-197 (appendix)
+        10 (expand-enc-key)
+    ] unit-test
 
-[ {
-    0x50a7f451 0x5365417e 0xc3a4171a 0x965e273a 0xcb6bab3b 0xf1459d1f 0xab58faac 0x9303e34b 
-    0x55fa3020 0xf66d76ad 0x9176cc88 0x254c02f5 0xfcd7e54f 0xd7cb2ac5 0x80443526 0x8fa362b5 
-    0x495ab1de 0x671bba25 0x980eea45 0xe1c0fe5d 0x02752fc3 0x12f04c81 0xa397468d 0xc6f9d36b 
-    0xe75f8f03 0x959c9215 0xeb7a6dbf 0xda595295 0x2d83bed4 0xd3217458 0x2969e049 0x44c8c98e 
-    0x6a89c275 0x78798ef4 0x6b3e5899 0xdd71b927 0xb64fe1be 0x17ad88f0 0x66ac20c9 0xb43ace7d 
-    0x184adf63 0x82311ae5 0x60335197 0x457f5362 0xe07764b1 0x84ae6bbb 0x1ca081fe 0x942b08f9 
-    0x58684870 0x19fd458f 0x876cde94 0xb7f87b52 0x23d373ab 0xe2024b72 0x578f1fe3 0x2aab5566 
-    0x0728ebb2 0x03c2b52f 0x9a7bc586 0xa50837d3 0xf2872830 0xb2a5bf23 0xba6a0302 0x5c8216ed 
-    0x2b1ccf8a 0x92b479a7 0xf0f207f3 0xa1e2694e 0xcdf4da65 0xd5be0506 0x1f6234d1 0x8afea6c4 
-    0x9d532e34 0xa055f3a2 0x32e18a05 0x75ebf6a4 0x39ec830b 0xaaef6040 0x069f715e 0x51106ebd 
-    0xf98a213e 0x3d06dd96 0xae053edd 0x46bde64d 0xb58d5491 0x055dc471 0x6fd40604 0xff155060 
-    0x24fb9819 0x97e9bdd6 0xcc434089 0x779ed967 0xbd42e8b0 0x888b8907 0x385b19e7 0xdbeec879 
-    0x470a7ca1 0xe90f427c 0xc91e84f8 0x00000000 0x83868009 0x48ed2b32 0xac70111e 0x4e725a6c 
-    0xfbff0efd 0x5638850f 0x1ed5ae3d 0x27392d36 0x64d90f0a 0x21a65c68 0xd1545b9b 0x3a2e3624 
-    0xb1670a0c 0x0fe75793 0xd296eeb4 0x9e919b1b 0x4fc5c080 0xa220dc61 0x694b775a 0x161a121c 
-    0x0aba93e2 0xe52aa0c0 0x43e0223c 0x1d171b12 0x0b0d090e 0xadc78bf2 0xb9a8b62d 0xc8a91e14 
-    0x8519f157 0x4c0775af 0xbbdd99ee 0xfd607fa3 0x9f2601f7 0xbcf5725c 0xc53b6644 0x347efb5b 
-    0x7629438b 0xdcc623cb 0x68fcedb6 0x63f1e4b8 0xcadc31d7 0x10856342 0x40229713 0x2011c684 
-    0x7d244a85 0xf83dbbd2 0x1132f9ae 0x6da129c7 0x4b2f9e1d 0xf330b2dc 0xec52860d 0xd0e3c177 
-    0x6c16b32b 0x99b970a9 0xfa489411 0x2264e947 0xc48cfca8 0x1a3ff0a0 0xd82c7d56 0xef903322 
-    0xc74e4987 0xc1d138d9 0xfea2ca8c 0x360bd498 0xcf81f5a6 0x28de7aa5 0x268eb7da 0xa4bfad3f 
-    0xe49d3a2c 0x0d927850 0x9bcc5f6a 0x62467e54 0xc2138df6 0xe8b8d890 0x5ef7392e 0xf5afc382 
-    0xbe805d9f 0x7c93d069 0xa92dd56f 0xb31225cf 0x3b99acc8 0xa77d1810 0x6e639ce8 0x7bbb3bdb 
-    0x097826cd 0xf418596e 0x01b79aec 0xa89a4f83 0x656e95e6 0x7ee6ffaa 0x08cfbc21 0xe6e815ef 
-    0xd99be7ba 0xce366f4a 0xd4099fea 0xd67cb029 0xafb2a431 0x31233f2a 0x3094a5c6 0xc066a235 
-    0x37bc4e74 0xa6ca82fc 0xb0d090e0 0x15d8a733 0x4a9804f1 0xf7daec41 0x0e50cd7f 0x2ff69117 
-    0x8dd64d76 0x4db0ef43 0x544daacc 0xdf0496e4 0xe3b5d19e 0x1b886a4c 0xb81f2cc1 0x7f516546 
-    0x04ea5e9d 0x5d358c01 0x737487fa 0x2e410bfb 0x5a1d67b3 0x52d2db92 0x335610e9 0x1347d66d 
-    0x8c61d79a 0x7a0ca137 0x8e14f859 0x893c13eb 0xee27a9ce 0x35c961b7 0xede51ce1 0x3cb1477a 
-    0x59dfd29c 0x3f73f255 0x79ce1418 0xbf37c773 0xeacdf753 0x5baafd5f 0x146f3ddf 0x86db4478 
-    0x81f3afca 0x3ec468b9 0x2c342438 0x5f40a3c2 0x72c31d16 0x0c25e2bc 0x8b493c28 0x41950dff 
-    0x7101a839 0xdeb30c08 0x9ce4b4d8 0x90c15664 0x6184cb7b 0x70b632d5 0x745c6c48 0x4257b8d0 
-    0xa7f45150 0x65417e53 0xa4171ac3 0x5e273a96 0x6bab3bcb 0x459d1ff1 0x58faacab 0x03e34b93 
-    0xfa302055 0x6d76adf6 0x76cc8891 0x4c02f525 0xd7e54ffc 0xcb2ac5d7 0x44352680 0xa362b58f 
-    0x5ab1de49 0x1bba2567 0x0eea4598 0xc0fe5de1 0x752fc302 0xf04c8112 0x97468da3 0xf9d36bc6 
-    0x5f8f03e7 0x9c921595 0x7a6dbfeb 0x595295da 0x83bed42d 0x217458d3 0x69e04929 0xc8c98e44 
-    0x89c2756a 0x798ef478 0x3e58996b 0x71b927dd 0x4fe1beb6 0xad88f017 0xac20c966 0x3ace7db4 
-    0x4adf6318 0x311ae582 0x33519760 0x7f536245 0x7764b1e0 0xae6bbb84 0xa081fe1c 0x2b08f994 
-    0x68487058 0xfd458f19 0x6cde9487 0xf87b52b7 0xd373ab23 0x024b72e2 0x8f1fe357 0xab55662a 
-    0x28ebb207 0xc2b52f03 0x7bc5869a 0x0837d3a5 0x872830f2 0xa5bf23b2 0x6a0302ba 0x8216ed5c 
-    0x1ccf8a2b 0xb479a792 0xf207f3f0 0xe2694ea1 0xf4da65cd 0xbe0506d5 0x6234d11f 0xfea6c48a 
-    0x532e349d 0x55f3a2a0 0xe18a0532 0xebf6a475 0xec830b39 0xef6040aa 0x9f715e06 0x106ebd51 
-    0x8a213ef9 0x06dd963d 0x053eddae 0xbde64d46 0x8d5491b5 0x5dc47105 0xd406046f 0x155060ff 
-    0xfb981924 0xe9bdd697 0x434089cc 0x9ed96777 0x42e8b0bd 0x8b890788 0x5b19e738 0xeec879db 
-    0x0a7ca147 0x0f427ce9 0x1e84f8c9 0x00000000 0x86800983 0xed2b3248 0x70111eac 0x725a6c4e 
-    0xff0efdfb 0x38850f56 0xd5ae3d1e 0x392d3627 0xd90f0a64 0xa65c6821 0x545b9bd1 0x2e36243a 
-    0x670a0cb1 0xe757930f 0x96eeb4d2 0x919b1b9e 0xc5c0804f 0x20dc61a2 0x4b775a69 0x1a121c16 
-    0xba93e20a 0x2aa0c0e5 0xe0223c43 0x171b121d 0x0d090e0b 0xc78bf2ad 0xa8b62db9 0xa91e14c8 
-    0x19f15785 0x0775af4c 0xdd99eebb 0x607fa3fd 0x2601f79f 0xf5725cbc 0x3b6644c5 0x7efb5b34 
-    0x29438b76 0xc623cbdc 0xfcedb668 0xf1e4b863 0xdc31d7ca 0x85634210 0x22971340 0x11c68420 
-    0x244a857d 0x3dbbd2f8 0x32f9ae11 0xa129c76d 0x2f9e1d4b 0x30b2dcf3 0x52860dec 0xe3c177d0 
-    0x16b32b6c 0xb970a999 0x489411fa 0x64e94722 0x8cfca8c4 0x3ff0a01a 0x2c7d56d8 0x903322ef 
-    0x4e4987c7 0xd138d9c1 0xa2ca8cfe 0x0bd49836 0x81f5a6cf 0xde7aa528 0x8eb7da26 0xbfad3fa4 
-    0x9d3a2ce4 0x9278500d 0xcc5f6a9b 0x467e5462 0x138df6c2 0xb8d890e8 0xf7392e5e 0xafc382f5 
-    0x805d9fbe 0x93d0697c 0x2dd56fa9 0x1225cfb3 0x99acc83b 0x7d1810a7 0x639ce86e 0xbb3bdb7b 
-    0x7826cd09 0x18596ef4 0xb79aec01 0x9a4f83a8 0x6e95e665 0xe6ffaa7e 0xcfbc2108 0xe815efe6 
-    0x9be7bad9 0x366f4ace 0x099fead4 0x7cb029d6 0xb2a431af 0x233f2a31 0x94a5c630 0x66a235c0 
-    0xbc4e7437 0xca82fca6 0xd090e0b0 0xd8a73315 0x9804f14a 0xdaec41f7 0x50cd7f0e 0xf691172f 
-    0xd64d768d 0xb0ef434d 0x4daacc54 0x0496e4df 0xb5d19ee3 0x886a4c1b 0x1f2cc1b8 0x5165467f 
-    0xea5e9d04 0x358c015d 0x7487fa73 0x410bfb2e 0x1d67b35a 0xd2db9252 0x5610e933 0x47d66d13 
-    0x61d79a8c 0x0ca1377a 0x14f8598e 0x3c13eb89 0x27a9ceee 0xc961b735 0xe51ce1ed 0xb1477a3c 
-    0xdfd29c59 0x73f2553f 0xce141879 0x37c773bf 0xcdf753ea 0xaafd5f5b 0x6f3ddf14 0xdb447886 
-    0xf3afca81 0xc468b93e 0x3424382c 0x40a3c25f 0xc31d1672 0x25e2bc0c 0x493c288b 0x950dff41 
-    0x01a83971 0xb30c08de 0xe4b4d89c 0xc1566490 0x84cb7b61 0xb632d570 0x5c6c4874 0x57b8d042 
-    0xf45150a7 0x417e5365 0x171ac3a4 0x273a965e 0xab3bcb6b 0x9d1ff145 0xfaacab58 0xe34b9303 
-    0x302055fa 0x76adf66d 0xcc889176 0x02f5254c 0xe54ffcd7 0x2ac5d7cb 0x35268044 0x62b58fa3 
-    0xb1de495a 0xba25671b 0xea45980e 0xfe5de1c0 0x2fc30275 0x4c8112f0 0x468da397 0xd36bc6f9 
-    0x8f03e75f 0x9215959c 0x6dbfeb7a 0x5295da59 0xbed42d83 0x7458d321 0xe0492969 0xc98e44c8 
-    0xc2756a89 0x8ef47879 0x58996b3e 0xb927dd71 0xe1beb64f 0x88f017ad 0x20c966ac 0xce7db43a 
-    0xdf63184a 0x1ae58231 0x51976033 0x5362457f 0x64b1e077 0x6bbb84ae 0x81fe1ca0 0x08f9942b 
-    0x48705868 0x458f19fd 0xde94876c 0x7b52b7f8 0x73ab23d3 0x4b72e202 0x1fe3578f 0x55662aab 
-    0xebb20728 0xb52f03c2 0xc5869a7b 0x37d3a508 0x2830f287 0xbf23b2a5 0x0302ba6a 0x16ed5c82 
-    0xcf8a2b1c 0x79a792b4 0x07f3f0f2 0x694ea1e2 0xda65cdf4 0x0506d5be 0x34d11f62 0xa6c48afe 
-    0x2e349d53 0xf3a2a055 0x8a0532e1 0xf6a475eb 0x830b39ec 0x6040aaef 0x715e069f 0x6ebd5110 
-    0x213ef98a 0xdd963d06 0x3eddae05 0xe64d46bd 0x5491b58d 0xc471055d 0x06046fd4 0x5060ff15 
-    0x981924fb 0xbdd697e9 0x4089cc43 0xd967779e 0xe8b0bd42 0x8907888b 0x19e7385b 0xc879dbee 
-    0x7ca1470a 0x427ce90f 0x84f8c91e 0x00000000 0x80098386 0x2b3248ed 0x111eac70 0x5a6c4e72 
-    0x0efdfbff 0x850f5638 0xae3d1ed5 0x2d362739 0x0f0a64d9 0x5c6821a6 0x5b9bd154 0x36243a2e 
-    0x0a0cb167 0x57930fe7 0xeeb4d296 0x9b1b9e91 0xc0804fc5 0xdc61a220 0x775a694b 0x121c161a 
-    0x93e20aba 0xa0c0e52a 0x223c43e0 0x1b121d17 0x090e0b0d 0x8bf2adc7 0xb62db9a8 0x1e14c8a9 
-    0xf1578519 0x75af4c07 0x99eebbdd 0x7fa3fd60 0x01f79f26 0x725cbcf5 0x6644c53b 0xfb5b347e 
-    0x438b7629 0x23cbdcc6 0xedb668fc 0xe4b863f1 0x31d7cadc 0x63421085 0x97134022 0xc6842011 
-    0x4a857d24 0xbbd2f83d 0xf9ae1132 0x29c76da1 0x9e1d4b2f 0xb2dcf330 0x860dec52 0xc177d0e3 
-    0xb32b6c16 0x70a999b9 0x9411fa48 0xe9472264 0xfca8c48c 0xf0a01a3f 0x7d56d82c 0x3322ef90 
-    0x4987c74e 0x38d9c1d1 0xca8cfea2 0xd498360b 0xf5a6cf81 0x7aa528de 0xb7da268e 0xad3fa4bf 
-    0x3a2ce49d 0x78500d92 0x5f6a9bcc 0x7e546246 0x8df6c213 0xd890e8b8 0x392e5ef7 0xc382f5af 
-    0x5d9fbe80 0xd0697c93 0xd56fa92d 0x25cfb312 0xacc83b99 0x1810a77d 0x9ce86e63 0x3bdb7bbb 
-    0x26cd0978 0x596ef418 0x9aec01b7 0x4f83a89a 0x95e6656e 0xffaa7ee6 0xbc2108cf 0x15efe6e8 
-    0xe7bad99b 0x6f4ace36 0x9fead409 0xb029d67c 0xa431afb2 0x3f2a3123 0xa5c63094 0xa235c066 
-    0x4e7437bc 0x82fca6ca 0x90e0b0d0 0xa73315d8 0x04f14a98 0xec41f7da 0xcd7f0e50 0x91172ff6 
-    0x4d768dd6 0xef434db0 0xaacc544d 0x96e4df04 0xd19ee3b5 0x6a4c1b88 0x2cc1b81f 0x65467f51 
-    0x5e9d04ea 0x8c015d35 0x87fa7374 0x0bfb2e41 0x67b35a1d 0xdb9252d2 0x10e93356 0xd66d1347 
-    0xd79a8c61 0xa1377a0c 0xf8598e14 0x13eb893c 0xa9ceee27 0x61b735c9 0x1ce1ede5 0x477a3cb1 
-    0xd29c59df 0xf2553f73 0x141879ce 0xc773bf37 0xf753eacd 0xfd5f5baa 0x3ddf146f 0x447886db 
-    0xafca81f3 0x68b93ec4 0x24382c34 0xa3c25f40 0x1d1672c3 0xe2bc0c25 0x3c288b49 0x0dff4195 
-    0xa8397101 0x0c08deb3 0xb4d89ce4 0x566490c1 0xcb7b6184 0x32d570b6 0x6c48745c 0xb8d04257 
-    0x5150a7f4 0x7e536541 0x1ac3a417 0x3a965e27 0x3bcb6bab 0x1ff1459d 0xacab58fa 0x4b9303e3 
-    0x2055fa30 0xadf66d76 0x889176cc 0xf5254c02 0x4ffcd7e5 0xc5d7cb2a 0x26804435 0xb58fa362 
-    0xde495ab1 0x25671bba 0x45980eea 0x5de1c0fe 0xc302752f 0x8112f04c 0x8da39746 0x6bc6f9d3 
-    0x03e75f8f 0x15959c92 0xbfeb7a6d 0x95da5952 0xd42d83be 0x58d32174 0x492969e0 0x8e44c8c9 
-    0x756a89c2 0xf478798e 0x996b3e58 0x27dd71b9 0xbeb64fe1 0xf017ad88 0xc966ac20 0x7db43ace 
-    0x63184adf 0xe582311a 0x97603351 0x62457f53 0xb1e07764 0xbb84ae6b 0xfe1ca081 0xf9942b08 
-    0x70586848 0x8f19fd45 0x94876cde 0x52b7f87b 0xab23d373 0x72e2024b 0xe3578f1f 0x662aab55 
-    0xb20728eb 0x2f03c2b5 0x869a7bc5 0xd3a50837 0x30f28728 0x23b2a5bf 0x02ba6a03 0xed5c8216 
-    0x8a2b1ccf 0xa792b479 0xf3f0f207 0x4ea1e269 0x65cdf4da 0x06d5be05 0xd11f6234 0xc48afea6 
-    0x349d532e 0xa2a055f3 0x0532e18a 0xa475ebf6 0x0b39ec83 0x40aaef60 0x5e069f71 0xbd51106e 
-    0x3ef98a21 0x963d06dd 0xddae053e 0x4d46bde6 0x91b58d54 0x71055dc4 0x046fd406 0x60ff1550 
-    0x1924fb98 0xd697e9bd 0x89cc4340 0x67779ed9 0xb0bd42e8 0x07888b89 0xe7385b19 0x79dbeec8 
-    0xa1470a7c 0x7ce90f42 0xf8c91e84 0x00000000 0x09838680 0x3248ed2b 0x1eac7011 0x6c4e725a 
-    0xfdfbff0e 0x0f563885 0x3d1ed5ae 0x3627392d 0x0a64d90f 0x6821a65c 0x9bd1545b 0x243a2e36 
-    0x0cb1670a 0x930fe757 0xb4d296ee 0x1b9e919b 0x804fc5c0 0x61a220dc 0x5a694b77 0x1c161a12 
-    0xe20aba93 0xc0e52aa0 0x3c43e022 0x121d171b 0x0e0b0d09 0xf2adc78b 0x2db9a8b6 0x14c8a91e 
-    0x578519f1 0xaf4c0775 0xeebbdd99 0xa3fd607f 0xf79f2601 0x5cbcf572 0x44c53b66 0x5b347efb 
-    0x8b762943 0xcbdcc623 0xb668fced 0xb863f1e4 0xd7cadc31 0x42108563 0x13402297 0x842011c6 
-    0x857d244a 0xd2f83dbb 0xae1132f9 0xc76da129 0x1d4b2f9e 0xdcf330b2 0x0dec5286 0x77d0e3c1 
-    0x2b6c16b3 0xa999b970 0x11fa4894 0x472264e9 0xa8c48cfc 0xa01a3ff0 0x56d82c7d 0x22ef9033 
-    0x87c74e49 0xd9c1d138 0x8cfea2ca 0x98360bd4 0xa6cf81f5 0xa528de7a 0xda268eb7 0x3fa4bfad 
-    0x2ce49d3a 0x500d9278 0x6a9bcc5f 0x5462467e 0xf6c2138d 0x90e8b8d8 0x2e5ef739 0x82f5afc3 
-    0x9fbe805d 0x697c93d0 0x6fa92dd5 0xcfb31225 0xc83b99ac 0x10a77d18 0xe86e639c 0xdb7bbb3b 
-    0xcd097826 0x6ef41859 0xec01b79a 0x83a89a4f 0xe6656e95 0xaa7ee6ff 0x2108cfbc 0xefe6e815 
-    0xbad99be7 0x4ace366f 0xead4099f 0x29d67cb0 0x31afb2a4 0x2a31233f 0xc63094a5 0x35c066a2 
-    0x7437bc4e 0xfca6ca82 0xe0b0d090 0x3315d8a7 0xf14a9804 0x41f7daec 0x7f0e50cd 0x172ff691 
-    0x768dd64d 0x434db0ef 0xcc544daa 0xe4df0496 0x9ee3b5d1 0x4c1b886a 0xc1b81f2c 0x467f5165 
-    0x9d04ea5e 0x015d358c 0xfa737487 0xfb2e410b 0xb35a1d67 0x9252d2db 0xe9335610 0x6d1347d6 
-    0x9a8c61d7 0x377a0ca1 0x598e14f8 0xeb893c13 0xceee27a9 0xb735c961 0xe1ede51c 0x7a3cb147 
-    0x9c59dfd2 0x553f73f2 0x1879ce14 0x73bf37c7 0x53eacdf7 0x5f5baafd 0xdf146f3d 0x7886db44 
-    0xca81f3af 0xb93ec468 0x382c3424 0xc25f40a3 0x1672c31d 0xbc0c25e2 0x288b493c 0xff41950d 
-    0x397101a8 0x08deb30c 0xd89ce4b4 0x6490c156 0x7b6184cb 0xd570b632 0x48745c6c 0xd04257b8 
-} ] [ d-table ] unit-test
+[ 0x046681e5 ] [ 0x088df419 ui32> t-transform ] unit-test
 
-[ {
-0xa56363c6 0x847c7cf8 0x997777ee 0x8d7b7bf6 0x0df2f2ff 0xbd6b6bd6 0xb16f6fde 0x54c5c591 
-0x50303060 0x03010102 0xa96767ce 0x7d2b2b56 0x19fefee7 0x62d7d7b5 0xe6abab4d 0x9a7676ec 
-0x45caca8f 0x9d82821f 0x40c9c989 0x877d7dfa 0x15fafaef 0xeb5959b2 0xc947478e 0x0bf0f0fb 
-0xecadad41 0x67d4d4b3 0xfda2a25f 0xeaafaf45 0xbf9c9c23 0xf7a4a453 0x967272e4 0x5bc0c09b 
-0xc2b7b775 0x1cfdfde1 0xae93933d 0x6a26264c 0x5a36366c 0x413f3f7e 0x02f7f7f5 0x4fcccc83 
-0x5c343468 0xf4a5a551 0x34e5e5d1 0x08f1f1f9 0x937171e2 0x73d8d8ab 0x53313162 0x3f15152a 
-0x0c040408 0x52c7c795 0x65232346 0x5ec3c39d 0x28181830 0xa1969637 0x0f05050a 0xb59a9a2f 
-0x0907070e 0x36121224 0x9b80801b 0x3de2e2df 0x26ebebcd 0x6927274e 0xcdb2b27f 0x9f7575ea 
-0x1b090912 0x9e83831d 0x742c2c58 0x2e1a1a34 0x2d1b1b36 0xb26e6edc 0xee5a5ab4 0xfba0a05b 
-0xf65252a4 0x4d3b3b76 0x61d6d6b7 0xceb3b37d 0x7b292952 0x3ee3e3dd 0x712f2f5e 0x97848413 
-0xf55353a6 0x68d1d1b9 0x00000000 0x2cededc1 0x60202040 0x1ffcfce3 0xc8b1b179 0xed5b5bb6 
-0xbe6a6ad4 0x46cbcb8d 0xd9bebe67 0x4b393972 0xde4a4a94 0xd44c4c98 0xe85858b0 0x4acfcf85 
-0x6bd0d0bb 0x2aefefc5 0xe5aaaa4f 0x16fbfbed 0xc5434386 0xd74d4d9a 0x55333366 0x94858511 
-0xcf45458a 0x10f9f9e9 0x06020204 0x817f7ffe 0xf05050a0 0x443c3c78 0xba9f9f25 0xe3a8a84b 
-0xf35151a2 0xfea3a35d 0xc0404080 0x8a8f8f05 0xad92923f 0xbc9d9d21 0x48383870 0x04f5f5f1 
-0xdfbcbc63 0xc1b6b677 0x75dadaaf 0x63212142 0x30101020 0x1affffe5 0x0ef3f3fd 0x6dd2d2bf 
-0x4ccdcd81 0x140c0c18 0x35131326 0x2fececc3 0xe15f5fbe 0xa2979735 0xcc444488 0x3917172e 
-0x57c4c493 0xf2a7a755 0x827e7efc 0x473d3d7a 0xac6464c8 0xe75d5dba 0x2b191932 0x957373e6 
-0xa06060c0 0x98818119 0xd14f4f9e 0x7fdcdca3 0x66222244 0x7e2a2a54 0xab90903b 0x8388880b 
-0xca46468c 0x29eeeec7 0xd3b8b86b 0x3c141428 0x79dedea7 0xe25e5ebc 0x1d0b0b16 0x76dbdbad 
-0x3be0e0db 0x56323264 0x4e3a3a74 0x1e0a0a14 0xdb494992 0x0a06060c 0x6c242448 0xe45c5cb8 
-0x5dc2c29f 0x6ed3d3bd 0xefacac43 0xa66262c4 0xa8919139 0xa4959531 0x37e4e4d3 0x8b7979f2 
-0x32e7e7d5 0x43c8c88b 0x5937376e 0xb76d6dda 0x8c8d8d01 0x64d5d5b1 0xd24e4e9c 0xe0a9a949 
-0xb46c6cd8 0xfa5656ac 0x07f4f4f3 0x25eaeacf 0xaf6565ca 0x8e7a7af4 0xe9aeae47 0x18080810 
-0xd5baba6f 0x887878f0 0x6f25254a 0x722e2e5c 0x241c1c38 0xf1a6a657 0xc7b4b473 0x51c6c697 
-0x23e8e8cb 0x7cdddda1 0x9c7474e8 0x211f1f3e 0xdd4b4b96 0xdcbdbd61 0x868b8b0d 0x858a8a0f 
-0x907070e0 0x423e3e7c 0xc4b5b571 0xaa6666cc 0xd8484890 0x05030306 0x01f6f6f7 0x120e0e1c 
-0xa36161c2 0x5f35356a 0xf95757ae 0xd0b9b969 0x91868617 0x58c1c199 0x271d1d3a 0xb99e9e27 
-0x38e1e1d9 0x13f8f8eb 0xb398982b 0x33111122 0xbb6969d2 0x70d9d9a9 0x898e8e07 0xa7949433 
-0xb69b9b2d 0x221e1e3c 0x92878715 0x20e9e9c9 0x49cece87 0xff5555aa 0x78282850 0x7adfdfa5 
-0x8f8c8c03 0xf8a1a159 0x80898909 0x170d0d1a 0xdabfbf65 0x31e6e6d7 0xc6424284 0xb86868d0 
-0xc3414182 0xb0999929 0x772d2d5a 0x110f0f1e 0xcbb0b07b 0xfc5454a8 0xd6bbbb6d 0x3a16162c 
-0x6363c6a5 0x7c7cf884 0x7777ee99 0x7b7bf68d 0xf2f2ff0d 0x6b6bd6bd 0x6f6fdeb1 0xc5c59154 
-0x30306050 0x01010203 0x6767cea9 0x2b2b567d 0xfefee719 0xd7d7b562 0xabab4de6 0x7676ec9a 
-0xcaca8f45 0x82821f9d 0xc9c98940 0x7d7dfa87 0xfafaef15 0x5959b2eb 0x47478ec9 0xf0f0fb0b 
-0xadad41ec 0xd4d4b367 0xa2a25ffd 0xafaf45ea 0x9c9c23bf 0xa4a453f7 0x7272e496 0xc0c09b5b 
-0xb7b775c2 0xfdfde11c 0x93933dae 0x26264c6a 0x36366c5a 0x3f3f7e41 0xf7f7f502 0xcccc834f 
-0x3434685c 0xa5a551f4 0xe5e5d134 0xf1f1f908 0x7171e293 0xd8d8ab73 0x31316253 0x15152a3f 
-0x0404080c 0xc7c79552 0x23234665 0xc3c39d5e 0x18183028 0x969637a1 0x05050a0f 0x9a9a2fb5 
-0x07070e09 0x12122436 0x80801b9b 0xe2e2df3d 0xebebcd26 0x27274e69 0xb2b27fcd 0x7575ea9f 
-0x0909121b 0x83831d9e 0x2c2c5874 0x1a1a342e 0x1b1b362d 0x6e6edcb2 0x5a5ab4ee 0xa0a05bfb 
-0x5252a4f6 0x3b3b764d 0xd6d6b761 0xb3b37dce 0x2929527b 0xe3e3dd3e 0x2f2f5e71 0x84841397 
-0x5353a6f5 0xd1d1b968 0x00000000 0xededc12c 0x20204060 0xfcfce31f 0xb1b179c8 0x5b5bb6ed 
-0x6a6ad4be 0xcbcb8d46 0xbebe67d9 0x3939724b 0x4a4a94de 0x4c4c98d4 0x5858b0e8 0xcfcf854a 
-0xd0d0bb6b 0xefefc52a 0xaaaa4fe5 0xfbfbed16 0x434386c5 0x4d4d9ad7 0x33336655 0x85851194 
-0x45458acf 0xf9f9e910 0x02020406 0x7f7ffe81 0x5050a0f0 0x3c3c7844 0x9f9f25ba 0xa8a84be3 
-0x5151a2f3 0xa3a35dfe 0x404080c0 0x8f8f058a 0x92923fad 0x9d9d21bc 0x38387048 0xf5f5f104 
-0xbcbc63df 0xb6b677c1 0xdadaaf75 0x21214263 0x10102030 0xffffe51a 0xf3f3fd0e 0xd2d2bf6d 
-0xcdcd814c 0x0c0c1814 0x13132635 0xececc32f 0x5f5fbee1 0x979735a2 0x444488cc 0x17172e39 
-0xc4c49357 0xa7a755f2 0x7e7efc82 0x3d3d7a47 0x6464c8ac 0x5d5dbae7 0x1919322b 0x7373e695 
-0x6060c0a0 0x81811998 0x4f4f9ed1 0xdcdca37f 0x22224466 0x2a2a547e 0x90903bab 0x88880b83 
-0x46468cca 0xeeeec729 0xb8b86bd3 0x1414283c 0xdedea779 0x5e5ebce2 0x0b0b161d 0xdbdbad76 
-0xe0e0db3b 0x32326456 0x3a3a744e 0x0a0a141e 0x494992db 0x06060c0a 0x2424486c 0x5c5cb8e4 
-0xc2c29f5d 0xd3d3bd6e 0xacac43ef 0x6262c4a6 0x919139a8 0x959531a4 0xe4e4d337 0x7979f28b 
-0xe7e7d532 0xc8c88b43 0x37376e59 0x6d6ddab7 0x8d8d018c 0xd5d5b164 0x4e4e9cd2 0xa9a949e0 
-0x6c6cd8b4 0x5656acfa 0xf4f4f307 0xeaeacf25 0x6565caaf 0x7a7af48e 0xaeae47e9 0x08081018 
-0xbaba6fd5 0x7878f088 0x25254a6f 0x2e2e5c72 0x1c1c3824 0xa6a657f1 0xb4b473c7 0xc6c69751 
-0xe8e8cb23 0xdddda17c 0x7474e89c 0x1f1f3e21 0x4b4b96dd 0xbdbd61dc 0x8b8b0d86 0x8a8a0f85 
-0x7070e090 0x3e3e7c42 0xb5b571c4 0x6666ccaa 0x484890d8 0x03030605 0xf6f6f701 0x0e0e1c12 
-0x6161c2a3 0x35356a5f 0x5757aef9 0xb9b969d0 0x86861791 0xc1c19958 0x1d1d3a27 0x9e9e27b9 
-0xe1e1d938 0xf8f8eb13 0x98982bb3 0x11112233 0x6969d2bb 0xd9d9a970 0x8e8e0789 0x949433a7 
-0x9b9b2db6 0x1e1e3c22 0x87871592 0xe9e9c920 0xcece8749 0x5555aaff 0x28285078 0xdfdfa57a 
-0x8c8c038f 0xa1a159f8 0x89890980 0x0d0d1a17 0xbfbf65da 0xe6e6d731 0x424284c6 0x6868d0b8 
-0x414182c3 0x999929b0 0x2d2d5a77 0x0f0f1e11 0xb0b07bcb 0x5454a8fc 0xbbbb6dd6 0x16162c3a 
-0x63c6a563 0x7cf8847c 0x77ee9977 0x7bf68d7b 0xf2ff0df2 0x6bd6bd6b 0x6fdeb16f 0xc59154c5 
-0x30605030 0x01020301 0x67cea967 0x2b567d2b 0xfee719fe 0xd7b562d7 0xab4de6ab 0x76ec9a76 
-0xca8f45ca 0x821f9d82 0xc98940c9 0x7dfa877d 0xfaef15fa 0x59b2eb59 0x478ec947 0xf0fb0bf0 
-0xad41ecad 0xd4b367d4 0xa25ffda2 0xaf45eaaf 0x9c23bf9c 0xa453f7a4 0x72e49672 0xc09b5bc0 
-0xb775c2b7 0xfde11cfd 0x933dae93 0x264c6a26 0x366c5a36 0x3f7e413f 0xf7f502f7 0xcc834fcc 
-0x34685c34 0xa551f4a5 0xe5d134e5 0xf1f908f1 0x71e29371 0xd8ab73d8 0x31625331 0x152a3f15 
-0x04080c04 0xc79552c7 0x23466523 0xc39d5ec3 0x18302818 0x9637a196 0x050a0f05 0x9a2fb59a 
-0x070e0907 0x12243612 0x801b9b80 0xe2df3de2 0xebcd26eb 0x274e6927 0xb27fcdb2 0x75ea9f75 
-0x09121b09 0x831d9e83 0x2c58742c 0x1a342e1a 0x1b362d1b 0x6edcb26e 0x5ab4ee5a 0xa05bfba0 
-0x52a4f652 0x3b764d3b 0xd6b761d6 0xb37dceb3 0x29527b29 0xe3dd3ee3 0x2f5e712f 0x84139784 
-0x53a6f553 0xd1b968d1 0x00000000 0xedc12ced 0x20406020 0xfce31ffc 0xb179c8b1 0x5bb6ed5b 
-0x6ad4be6a 0xcb8d46cb 0xbe67d9be 0x39724b39 0x4a94de4a 0x4c98d44c 0x58b0e858 0xcf854acf 
-0xd0bb6bd0 0xefc52aef 0xaa4fe5aa 0xfbed16fb 0x4386c543 0x4d9ad74d 0x33665533 0x85119485 
-0x458acf45 0xf9e910f9 0x02040602 0x7ffe817f 0x50a0f050 0x3c78443c 0x9f25ba9f 0xa84be3a8 
-0x51a2f351 0xa35dfea3 0x4080c040 0x8f058a8f 0x923fad92 0x9d21bc9d 0x38704838 0xf5f104f5 
-0xbc63dfbc 0xb677c1b6 0xdaaf75da 0x21426321 0x10203010 0xffe51aff 0xf3fd0ef3 0xd2bf6dd2 
-0xcd814ccd 0x0c18140c 0x13263513 0xecc32fec 0x5fbee15f 0x9735a297 0x4488cc44 0x172e3917 
-0xc49357c4 0xa755f2a7 0x7efc827e 0x3d7a473d 0x64c8ac64 0x5dbae75d 0x19322b19 0x73e69573 
-0x60c0a060 0x81199881 0x4f9ed14f 0xdca37fdc 0x22446622 0x2a547e2a 0x903bab90 0x880b8388 
-0x468cca46 0xeec729ee 0xb86bd3b8 0x14283c14 0xdea779de 0x5ebce25e 0x0b161d0b 0xdbad76db 
-0xe0db3be0 0x32645632 0x3a744e3a 0x0a141e0a 0x4992db49 0x060c0a06 0x24486c24 0x5cb8e45c 
-0xc29f5dc2 0xd3bd6ed3 0xac43efac 0x62c4a662 0x9139a891 0x9531a495 0xe4d337e4 0x79f28b79 
-0xe7d532e7 0xc88b43c8 0x376e5937 0x6ddab76d 0x8d018c8d 0xd5b164d5 0x4e9cd24e 0xa949e0a9 
-0x6cd8b46c 0x56acfa56 0xf4f307f4 0xeacf25ea 0x65caaf65 0x7af48e7a 0xae47e9ae 0x08101808 
-0xba6fd5ba 0x78f08878 0x254a6f25 0x2e5c722e 0x1c38241c 0xa657f1a6 0xb473c7b4 0xc69751c6 
-0xe8cb23e8 0xdda17cdd 0x74e89c74 0x1f3e211f 0x4b96dd4b 0xbd61dcbd 0x8b0d868b 0x8a0f858a 
-0x70e09070 0x3e7c423e 0xb571c4b5 0x66ccaa66 0x4890d848 0x03060503 0xf6f701f6 0x0e1c120e 
-0x61c2a361 0x356a5f35 0x57aef957 0xb969d0b9 0x86179186 0xc19958c1 0x1d3a271d 0x9e27b99e 
-0xe1d938e1 0xf8eb13f8 0x982bb398 0x11223311 0x69d2bb69 0xd9a970d9 0x8e07898e 0x9433a794 
-0x9b2db69b 0x1e3c221e 0x87159287 0xe9c920e9 0xce8749ce 0x55aaff55 0x28507828 0xdfa57adf 
-0x8c038f8c 0xa159f8a1 0x89098089 0x0d1a170d 0xbf65dabf 0xe6d731e6 0x4284c642 0x68d0b868 
-0x4182c341 0x9929b099 0x2d5a772d 0x0f1e110f 0xb07bcbb0 0x54a8fc54 0xbb6dd6bb 0x162c3a16 
-0xc6a56363 0xf8847c7c 0xee997777 0xf68d7b7b 0xff0df2f2 0xd6bd6b6b 0xdeb16f6f 0x9154c5c5 
-0x60503030 0x02030101 0xcea96767 0x567d2b2b 0xe719fefe 0xb562d7d7 0x4de6abab 0xec9a7676 
-0x8f45caca 0x1f9d8282 0x8940c9c9 0xfa877d7d 0xef15fafa 0xb2eb5959 0x8ec94747 0xfb0bf0f0 
-0x41ecadad 0xb367d4d4 0x5ffda2a2 0x45eaafaf 0x23bf9c9c 0x53f7a4a4 0xe4967272 0x9b5bc0c0 
-0x75c2b7b7 0xe11cfdfd 0x3dae9393 0x4c6a2626 0x6c5a3636 0x7e413f3f 0xf502f7f7 0x834fcccc 
-0x685c3434 0x51f4a5a5 0xd134e5e5 0xf908f1f1 0xe2937171 0xab73d8d8 0x62533131 0x2a3f1515 
-0x080c0404 0x9552c7c7 0x46652323 0x9d5ec3c3 0x30281818 0x37a19696 0x0a0f0505 0x2fb59a9a 
-0x0e090707 0x24361212 0x1b9b8080 0xdf3de2e2 0xcd26ebeb 0x4e692727 0x7fcdb2b2 0xea9f7575 
-0x121b0909 0x1d9e8383 0x58742c2c 0x342e1a1a 0x362d1b1b 0xdcb26e6e 0xb4ee5a5a 0x5bfba0a0 
-0xa4f65252 0x764d3b3b 0xb761d6d6 0x7dceb3b3 0x527b2929 0xdd3ee3e3 0x5e712f2f 0x13978484 
-0xa6f55353 0xb968d1d1 0x00000000 0xc12ceded 0x40602020 0xe31ffcfc 0x79c8b1b1 0xb6ed5b5b 
-0xd4be6a6a 0x8d46cbcb 0x67d9bebe 0x724b3939 0x94de4a4a 0x98d44c4c 0xb0e85858 0x854acfcf 
-0xbb6bd0d0 0xc52aefef 0x4fe5aaaa 0xed16fbfb 0x86c54343 0x9ad74d4d 0x66553333 0x11948585 
-0x8acf4545 0xe910f9f9 0x04060202 0xfe817f7f 0xa0f05050 0x78443c3c 0x25ba9f9f 0x4be3a8a8 
-0xa2f35151 0x5dfea3a3 0x80c04040 0x058a8f8f 0x3fad9292 0x21bc9d9d 0x70483838 0xf104f5f5 
-0x63dfbcbc 0x77c1b6b6 0xaf75dada 0x42632121 0x20301010 0xe51affff 0xfd0ef3f3 0xbf6dd2d2 
-0x814ccdcd 0x18140c0c 0x26351313 0xc32fecec 0xbee15f5f 0x35a29797 0x88cc4444 0x2e391717 
-0x9357c4c4 0x55f2a7a7 0xfc827e7e 0x7a473d3d 0xc8ac6464 0xbae75d5d 0x322b1919 0xe6957373 
-0xc0a06060 0x19988181 0x9ed14f4f 0xa37fdcdc 0x44662222 0x547e2a2a 0x3bab9090 0x0b838888 
-0x8cca4646 0xc729eeee 0x6bd3b8b8 0x283c1414 0xa779dede 0xbce25e5e 0x161d0b0b 0xad76dbdb 
-0xdb3be0e0 0x64563232 0x744e3a3a 0x141e0a0a 0x92db4949 0x0c0a0606 0x486c2424 0xb8e45c5c 
-0x9f5dc2c2 0xbd6ed3d3 0x43efacac 0xc4a66262 0x39a89191 0x31a49595 0xd337e4e4 0xf28b7979 
-0xd532e7e7 0x8b43c8c8 0x6e593737 0xdab76d6d 0x018c8d8d 0xb164d5d5 0x9cd24e4e 0x49e0a9a9 
-0xd8b46c6c 0xacfa5656 0xf307f4f4 0xcf25eaea 0xcaaf6565 0xf48e7a7a 0x47e9aeae 0x10180808 
-0x6fd5baba 0xf0887878 0x4a6f2525 0x5c722e2e 0x38241c1c 0x57f1a6a6 0x73c7b4b4 0x9751c6c6 
-0xcb23e8e8 0xa17cdddd 0xe89c7474 0x3e211f1f 0x96dd4b4b 0x61dcbdbd 0x0d868b8b 0x0f858a8a 
-0xe0907070 0x7c423e3e 0x71c4b5b5 0xccaa6666 0x90d84848 0x06050303 0xf701f6f6 0x1c120e0e 
-0xc2a36161 0x6a5f3535 0xaef95757 0x69d0b9b9 0x17918686 0x9958c1c1 0x3a271d1d 0x27b99e9e 
-0xd938e1e1 0xeb13f8f8 0x2bb39898 0x22331111 0xd2bb6969 0xa970d9d9 0x07898e8e 0x33a79494 
-0x2db69b9b 0x3c221e1e 0x15928787 0xc920e9e9 0x8749cece 0xaaff5555 0x50782828 0xa57adfdf 
-0x038f8c8c 0x59f8a1a1 0x09808989 0x1a170d0d 0x65dabfbf 0xd731e6e6 0x84c64242 0xd0b86868 
-0x82c34141 0x29b09999 0x5a772d2d 0x1e110f0f 0x7bcbb0b0 0xa8fc5454 0x6dd6bbbb 0x2c3a1616 
-} ] [ t-table ] unit-test
+[ V{
+    0x3925841d
+    0x02dc09fb
+    0xdc118597
+    0x196a0b32
+ }
+] [
+    key plaintext aes-encrypt-block bytes>words
+] unit-test
 
+[ t ] [
+    sbox [ dup inv-sbox nth sbox nth = ] all?
+] unit-test
\ No newline at end of file
index a1e6e470d5d76a4d51e4d018dd6b5ac5ce14c83b..3bd6377657d333f3ffe09aae1c6f0ab2b4e54a58 100644 (file)
@@ -1,10 +1,25 @@
-! Copyright (C) 2008 Doug Coleman.
+! Copyright (C) 2013 Fred Alger
+! Some parts Copyright (C) 2008 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: arrays kernel math memoize sequences math.bitwise
-locals ;
+USING: accessors arrays assocs combinators crypto.aes.utils
+generalizations grouping kernel locals math math.bitwise
+math.ranges memoize namespaces sequences sequences.private
+sequences.unrolled ;
 IN: crypto.aes
 
 CONSTANT: AES_BLOCK_SIZE 16
+#! FIPS-197 AES
+#! input block, state, output block -- 4 32-bit words
+CONSTANT: FIPS-197 {
+    { 128 10 } #! aes-128 -- Key(4) Block(4) Rounds(10)
+    { 192 12 } #! aes-192 -- Key(6) Block(4) Rounds(12)
+    { 256 14 } #! aes-256 -- Key(8) Block(4) Rounds(14)
+}
+
+<PRIVATE
+
+: (nrounds) ( byte-array -- rounds )
+    length 8 * FIPS-197 at ;
 
 : sbox ( -- array )
 {
@@ -46,68 +61,254 @@ CONSTANT: AES_BLOCK_SIZE 16
     256 0 <array>
     dup 256 [ dup sbox nth rot set-nth ] with each-integer ;
 
+#! applies sbox to each byte of word
+: subword ( word -- word' )
+    [ gb0 sbox nth ] keep [ gb1 sbox nth ] keep
+    [ gb2 sbox nth ] keep gb3 sbox nth >ui32 ;
+
+#! applies inverse sbox to each byte of word
+: inv-subword ( word -- word' )
+    [ gb0 inv-sbox nth ] keep [ gb1 inv-sbox nth ] keep
+    [ gb2 inv-sbox nth ] keep gb3 inv-sbox nth >ui32 ;
+
+: rotword ( n -- n ) 8 bitroll-32 ;
+
+#! round constants, 2^n over GF(2^8)
 : rcon ( -- array )
     {
         0x00 0x01 0x02 0x04 0x08 0x10
         0x20 0x40 0x80 0x1b 0x36
     } ;
 
+: (rcon-nth) ( n -- rcon[n] ) rcon nth 24 shift ;
+
+#! Galois field product related
 : xtime ( x -- x' )
     [ 1 shift ]
     [ 0x80 bitand 0 = 0 0x1b ? ] bi bitxor 8 bits ;
 
-: ui32 ( a0 a1 a2 a3 -- a )
-    [ 8 shift ] [ 16 shift ] [ 24 shift ] tri*
-    bitor bitor bitor 32 bits ;
-
+#! generate t-box
 :: set-t ( T i -- )
     i sbox nth :> a1
     a1 xtime :> a2
     a1 a2 bitxor :> a3
 
-    a2 a1 a1 a3 ui32 i T set-nth
-    a3 a2 a1 a1 ui32 i 0x100 + T set-nth
-    a1 a3 a2 a1 ui32 i 0x200 + T set-nth
-    a1 a1 a3 a2 ui32 i 0x300 + T set-nth ;
+    a3 a1 a1 a2 >ui32 i T set-nth
+    a1 a1 a2 a3 >ui32 i 0x100 + T set-nth
+    a1 a2 a3 a1 >ui32 i 0x200 + T set-nth
+    a2 a3 a1 a1 >ui32 i 0x300 + T set-nth ;
 
 MEMO:: t-table ( -- array )
     1024 0 <array>
     dup 256 [ set-t ] with each-integer ;
 
+#! generate inverse t-box
 :: set-d ( D i -- )
     i inv-sbox nth :> a1
     a1 xtime :> a2
     a2 xtime :> a4
     a4 xtime :> a8
-    a8 a1 bitxor :> a9
+    a8 a1 bitxor :> a9 
     a9 a2 bitxor :> ab
     a9 a4 bitxor :> ad
     a8 a4 a2 bitxor bitxor :> ae
 
-    ae a9 ad ab ui32 i D set-nth
-    ab ae a9 ad ui32 i 0x100 + D set-nth
-    ad ab ae a9 ui32 i 0x200 + D set-nth
-    a9 ad ab ae ui32 i 0x300 + D set-nth ;
-    
+    ab ad a9 ae >ui32 i D set-nth
+    ad a9 ae ab >ui32 i 0x100 + D set-nth
+    a9 ae ab ad >ui32 i 0x200 + D set-nth
+    ae ab ad a9 >ui32 i 0x300 + D set-nth ;
+
 MEMO:: d-table ( -- array )
     1024 0 <array>
     dup 256 [ set-d ] with each-integer ;
 
 
-USE: multiline
-/*
-! : HT ( i x s -- 
+:: (transform) ( a0 a1 a2 a3 table -- word' )
+  a0 a1 a2 a3
+  [ 0x100 + ] [ 0x200 + ] [ 0x300 + ] tri*
+  [ table nth ] 4 napply
+  bitxor bitxor bitxor ; inline
+
+: t-transform ( a0 a1 a2 a3 -- word' ) t-table (transform) ;
+: d-transform ( a0 a1 a2 a3 -- word' ) d-table (transform) ;
+
+#! key schedule
+#! expands an 128/192/256 bit key into an 176/208/240 byte schedule
+
+SYMBOL: aes-expand-inner
+HOOK: key-expand-round aes-expand-inner  ( temp i -- temp' )
+
+SINGLETON: aes-128-key
+SINGLETON: aes-256-key
+
+: (add-rcon) ( word rcon-ndx -- word' )
+    (rcon-nth) [ rotword subword ] dip bitxor ;
+
+M: aes-128-key key-expand-round ( temp i -- temp' )
+    4 /mod 0 = swap and [ (add-rcon) ] when* ;
+
+ERROR: aes-192-256-not-implemented* ;
+M: aes-256-key key-expand-round ( temp i -- temp' )
+    aes-192-256-not-implemented* ;
+
+: (key-sched-round) ( output temp i -- output' )
+    key-expand-round
+    [ dup 4th-from-end ] dip bitxor suffix! ; inline
+
+: (sched-interval) ( K Nr -- seq )
+    [ length ] dip 1 + 4 * [a,b) ;    #! over the interval Nk...Nb(Nr + 1)
+
+: (init-round) ( out -- out temp quot )
+    [ ]
+    [ last ]
+    [
+        length
+        6 > [ aes-256-key ] [ aes-128-key ] if
+    ] tri ;
+
+#! K -- input key (byte-array), Nr -- number of rounds
+#! output: sched, Nb(Nr+1) byte key schedule
+: (expand-enc-key) ( K Nr -- sched )
+    [ bytes>words ] dip
+    [ drop (init-round) ]
+    [ (sched-interval) ] 2bi
+    [
+        [ aes-expand-inner set ] dip
+        [ (key-sched-round) dup last ] each
+    ] with-scope
+    drop ;
+
+TUPLE: aes-state nrounds key state ;
+
+: <aes> ( nrounds key state -- aes-state ) \ aes-state boa ; 
 
+#! grabs the 4n...4(n+1) words of the key
+: (key-at-nth-round) ( nth aes -- seq )
+    [ 4 * dup 4 + ] [ key>> ] bi* <slice> ;
 
-TUPLE: caes #rounds2 rkey ;
-! rounds / 2, rkey is a byte-array 60 long
-! key size is 16, 24, 32 bytes
+SYMBOL: aes-strategy
+HOOK: (expand-key) aes-strategy ( K Nr -- sched )
+HOOK: (first-round) aes-strategy ( aes -- aes' )
+HOOK: (counter) aes-strategy ( nrounds -- seq )
+HOOK: (round) aes-strategy ( state -- ) 
+HOOK: (add-key) aes-strategy ( aes -- aes' )
+HOOK: (final-round) aes-strategy ( aes -- aes' ) 
 
-TUPLE: caescbc prev4 caes ;
+SINGLETON: aes-decrypt
+SINGLETON: aes-encrypt
 
 
+#! rotates the 2nd row left by one element
+#! rotates the 3rd row left by two elements
+#! rotates the 4th row left by three elements
+#!
+#! Kind of ugly because the algorithm is specified and
+#! implemented in terms of columns. This approach is very
+#! efficient in terms of execution and only requires one new
+#! word to implement.
+#!
+#! The alternative is to split into arrays of bytes, transpose,
+#! rotate each row n times, transpose again, and then
+#! smash them back into 4-byte words.
+:: (shift-rows) ( c0 c1 c2 c3 -- c0' c1' c2' c3' )
+    c3 gb0   c2 gb1   c1 gb2   c0 gb3   >ui32   #! c0'
+    c0 gb0   c3 gb1   c2 gb2   c1 gb3   >ui32   #! c1'
+    c1 gb0   c0 gb1   c3 gb2   c2 gb3   >ui32   #! c2'
+    c2 gb0   c1 gb1   c0 gb2   c3 gb3   >ui32 ; #! c3'
 
-: aes-set-key-encode ( p key -- )
+:: (unshift-rows) ( c0 c1 c2 c3 -- c0' c1' c2' c3' )
+    c1 gb0   c2 gb1   c3 gb2   c0 gb3   >ui32   #! c0'
+    c2 gb0   c3 gb1   c0 gb2   c1 gb3   >ui32   #! c1'
+    c3 gb0   c0 gb1   c1 gb2   c2 gb3   >ui32   #! c2'
+    c0 gb0   c1 gb1   c2 gb2   c3 gb3   >ui32 ; #! c3'
+
+: (add-round-key) ( key state -- state' )
+   4 [ bitxor ] unrolled-2map ;
+
+: add-round-key ( aes n -- aes' )
+    over (key-at-nth-round) swap
+    [ (add-round-key) ] change-state ;
+
+: add-final-round-key ( aes -- aes' )
+    dup nrounds>> add-round-key ;
+
+: add-first-round-key ( aes -- aes' )
+    0 add-round-key ;
+
+: aes-round ( state -- )
+    dup first4-unsafe
+    { [ first-diag t-transform ]
+      [ second-diag t-transform ]
+      [ third-diag t-transform ]
+      [ fourth-diag t-transform ] } 4 ncleave
+      set-first4-unsafe ;
+
+
+: shift-rows ( state -- state' )
+    first4 (shift-rows) 4array ;
+
+: unshift-rows ( state -- state' )
+    first4 (unshift-rows) 4array ;
+
+: final-round ( state -- state' )
+    4 [ subword ] unrolled-map shift-rows ;
+
+: (do-round) ( aes -- aes' )
+    [ state>> (round) ] keep ;
+
+M: aes-encrypt (expand-key) (expand-enc-key) ;
+M: aes-encrypt (first-round) add-first-round-key ;
+M: aes-encrypt (counter) 0 swap (a,b) ;
+M: aes-encrypt (round) aes-round ;
+M: aes-encrypt (final-round) [ final-round ] change-state add-final-round-key ;
+
+M:: aes-decrypt (expand-key) ( K Nr -- sched )
+    K Nr (expand-enc-key) dup length :> key-length
+    [
+        [ 4 >= ] [ key-length 4 - < ] bi and
+        [ subword ui32-rev> d-transform ]
+        [ ] if
+    ] map-index ;
+
+M: aes-decrypt (first-round) ( aes -- aes' )
+    add-final-round-key ;
+
+M: aes-decrypt (counter) ( nrounds -- seq ) 0 swap (a,b) <reversed> ;
+M: aes-decrypt (final-round) ( aes -- aes' )
+    [ [ inv-subword ] map unshift-rows  ] change-state
+    add-first-round-key ;
+
+M: aes-decrypt (round) ( state -- )
+    dup first4-unsafe
+    { [ -first-diag d-transform ]
+      [ -fourth-diag d-transform ]
+      [ -third-diag d-transform ]
+      [ -second-diag d-transform ] } 4 ncleave
+      set-first4-unsafe ;
+
+
+: (aes-crypt) ( aes -- aes' )
+    (first-round) [
+        dup nrounds>> (counter)
+        [ [ (do-round) ] dip add-round-key drop ] with each
+    ] keep
+    (final-round) ;
+
+: (aes-expand-key) ( key -- nrounds expanded-key )
+    [ (nrounds) ] keep over (expand-key) ;
+
+: (aes-crypt-block-inner) ( nrounds key block -- crypted-block )
+    <aes> (aes-crypt) state>> ;
     
-    ;
-*/
+: (aes-crypt-block) ( key block -- output-block )
+    [ (aes-expand-key) ] dip bytes>words (aes-crypt-block-inner) ;
+
+PRIVATE>
+
+: aes-encrypt-block ( key block -- output )
+    [ aes-encrypt aes-strategy set (aes-crypt-block) ] with-scope
+    [ ui32> 4array reverse ] map concat ;
+
+: aes-decrypt-block ( key block -- output )
+    [ aes-decrypt aes-strategy set (aes-crypt-block) ] with-scope
+    [ ui32> 4array reverse ] map concat ;
index b4bd0e7b35e6a8f0d41992b7e7faba52bb7d25da..e635ea364561afafef53e414356fe2b0f2b60f6c 100644 (file)
@@ -1 +1,2 @@
-Doug Coleman
\ No newline at end of file
+Doug Coleman
+Fred Alger
diff --git a/extra/crypto/aes/utils/utils.factor b/extra/crypto/aes/utils/utils.factor
new file mode 100644 (file)
index 0000000..d4606aa
--- /dev/null
@@ -0,0 +1,64 @@
+! Copyright (C) 2013 Fred Alger
+! See http://factorcode.org/license.txt for BSD license.
+USING: arrays columns combinators generalizations grouping
+kernel locals math math.bitwise prettyprint sequences
+sequences.private ;
+IN: crypto.aes.utils
+: gb0 ( a -- a0 ) 0xff bitand ; inline
+: gb1 ( a -- a1 ) -8 shift gb0 ; inline
+: gb2 ( a -- a2 ) -16 shift gb0 ; inline
+: gb3 ( a -- a3 ) -24 shift gb0 ; inline
+
+#! pack 4 bytes into 32-bit unsigned int
+#!  a3 is msb
+: >ui32 ( a0 a1 a2 a3 -- a )
+    [ 8 shift ] [ 16 shift ] [ 24 shift ] tri*
+    bitor bitor bitor 32 bits ;
+
+#! inverse of ui32
+: ui32> ( word -- a0 a1 a2 a3 )
+    [ gb0 ] keep [ gb1 ] keep [ gb2 ] keep gb3 ; inline
+
+: ui32-rev> ( word -- a3 a2 a1 a0 )
+    [ gb3 ] keep [ gb2 ] keep [ gb1 ] keep gb0 ; inline
+
+: bytes>words ( seq -- seq )
+    4 <sliced-groups> [ <reversed> first4 >ui32 ] V{ } map-as ;
+
+: .t ( seq -- )
+    reverse
+    {
+        [ [ gb0 ] map first4 >ui32 ]
+        [ [ gb1 ] map first4 >ui32 ]
+        [ [ gb2 ] map first4 >ui32 ]
+        [ [ gb3 ] map first4 >ui32 ]
+    } cleave .h .h .h .h ;
+
+
+#! given 4 columns, output the first diagonal, i.e.
+#!  C[0,0] C[1,1] C[2,2] C[3,3]
+: first-diag ( c0 c1 c2 c3 -- a0 a1 a2 a3 )
+    { [ gb3 ] [ gb2 ] [ gb1 ] [ gb0 ] } spread ;
+
+: (4rot) ( c0 c1 c2 c3 -- c1 c2 c3 c0 ) 4 nrot ; inline
+: second-diag ( c0 c1 c2 c3 -- a0 a1 a2 a3 ) (4rot) first-diag ;
+: third-diag  ( c0 c1 c2 c3 -- a0 a1 a2 a3 ) (4rot) second-diag ;
+: fourth-diag ( c0 c1 c2 c3 -- a0 a1 a2 a3 ) (4rot) third-diag ;
+
+#! given 4 columns, output the first reverse diagonal, i.e.
+#!  C[0,0] C[3,1] C[2,2] C[1,3]
+:: (-rev) ( c0 c1 c2 c3 -- c0 c3 c2 c1 ) c0 c3 c2 c1 ; inline
+: -first-diag  ( c0 c1 c2 c3 -- a0 a1 a2 a3 ) (-rev) first-diag ;
+: -second-diag ( c0 c1 c2 c3 -- a0 a1 a2 a3 ) (-rev) (4rot) first-diag ;
+: -third-diag  ( c0 c1 c2 c3 -- a0 a1 a2 a3 ) (-rev) (4rot) second-diag ;
+: -fourth-diag ( c0 c1 c2 c3 -- a0 a1 a2 a3 ) (-rev) (4rot) third-diag ;
+
+:: set-first4-unsafe ( seq a0 a1 a2 a3 -- )
+    a0 0 seq set-nth-unsafe
+    a1 1 seq set-nth-unsafe
+    a2 2 seq set-nth-unsafe
+    a3 3 seq set-nth-unsafe ;
+
+: 4th-from-end ( seq -- el )
+    [ length 4 - ] keep nth ;
+