The Advanced Encryption Standard (alternate ), or AES, the U.S. National Institute of Standards and Technology Federal Information Processing Standards Publication 197, specifies the Rijndael block cipher, which supercedes the DES cipher.

See Also

aes with critcl
A C implemenation of AES using critcl.


AES supports variable key and block sizes. The standard specifies a block of 128 bits, and the only permitted key sizes are 128, 192 or 256 bits. AES should be used in preference to DES in all new protocol designs.

The aes module in Tcllib version 1.8 and later provides a pure-Tcl implementation of AES, and in the module-aes branch also provides an accelerated implementation written in C using critcl, for which there is a usage fee. To use it:

package require aes
aes::Accelerate 1

aes::aes automatically pads the input with with NUL characters so that its length is an even multiple of 16. Decrypting the encrypted value does not automatically remove the extra padding characters. The caller must either avoid this automatic padding by using a pidding scheme of its own, perhaps the specified in rfc 2315 , before passing the input to aes::aes, or arrange to somehow remove the padded characters by keeping track of the length of the input data.


package require aes
set key [string repeat - 16]
set fullData {MalletData 9 q q q2 22}
set encryptedData [aes::aes -dir encrypt -key $key $fullData]
set decrypted [aes::aes -dir decrypt -key $key $encryptedData]
puts [list {original data length} [string length $fullData
        ] {decrypted data length} [string length $decrypted]]


{original data length} 22 {decrypted data length} 32

Invalid Issue Report: Invalid Output

AndyA: Has this been validated against an authoritative aes example? Using aes 1.2.1 with tcllib 1.18 and tcl 8.6.4, on 64-bit windows firstly the example given in the documentation doesn't work:

% set nil_block [string repeat \\0 16]
% aes::aes -hex -mode cbc -dir encrypt -key $nil_block $nil_block

Whereas I get:


(note different length!)

Then when I validate the Tcllib aes against it gives different results. Whereas I have written my own wrapper over B Gladman C code that is consistent with the website. I had actually been hoping to use the tcllib aes wrapper to validate my own code!

So I suspect this library is untested, or only tested on a very specific (32-bit?) platform

It's a bug in aes.tcl. After calling "binary scan binary-array I var", the numbers in var should be converted to unsigned 32-bit integers. You can define a procedure to do this.

proc ::aes::to_unsigned data {
        upvar $data d
        set i 0
        foreach num $d {
                lset d $i [expr { $num & 0xffffffff }]
                incr i

There are 5 places to do the convertion, 2 in ::aes::EncryptBlock, 2 in ::aes::DecryptBlock and 1 in ::aes::ExpandKey. You should call to_unsigned after calling of binary scan, like this:

# original code
if {[binary scan $block I4 data] != 1} {
        return -code error "invalid block size: blocks must be 16 bytes"
# bug-fix add here
to_unsigned data

2011-01-08: Or better yet, if you have 8.5, use the unsigned flag to binary scan, changing your "binary scan binary-array I var" to "binary scan binary-array Iu var".

Then the example code snippet just needs to read:

if {[binary scan $block Iu4 data] != 1} ...

pyk 2022-04-24: The binary scan issues were already fixed in some earlier version of the aes module, and they aren't related to the invalid output problem reported above. The example in the in the documentation uses too many backslashes. One backslash should be removed, like this:

% package require aes
% set nil_block [string repeat \0 16]
% aes::aes -hex -mode cbc -dir encrypt -key $nil_block $nil_block

Page Authors

Added usage details for Tcllib's AES module.