Hi Gabriel,
I created a paste with your code at
https://paste.factorcode.org/paste?id=2949 so that long snippets of code
can be posted there instead of the mailing list.

Here's what I would change at first glance:
- "rot-word" is similar to "rotate" in sequences.extras, maybe use that one
instead
- "1 tail" is "rest" in sequences.
- "11 0 <array> 0x01 [ drop xtime ] accumulate nip" -> use "replicate" and
keep the value on the stack
- "4 iota [ X ] 2map" -> [ X ] map-index (and 4 head if the first sequence
is longer than 4 elements)
- [ [ xtime ] times 0 ? ] with map-index -> you are doing the computation
and thowing the result away for unset bits. did you intend to do it to
simplify the stack shuffling ?

Otherwise, it looks pretty idiomatic.

Cheers,
Jon


On Sun, May 26, 2013 at 8:42 PM, Gabriel Kerneis <gabr...@kerneis.info>
wrote:
>
> Dear all,
>
> I've just started (re)learning Factor.  As an exercise, I implemented AES
(the
> crypto.aes library has never been finished).  Since I still have so much
to
> learn about Factor, I'd be grateful if you could review the code and give
me
> some hints about style, efficiency, etc.
>
> Preliminary note: it would be much more efficient to use lookup tables
(such as
> t-table and d-table provided by crypto.aes), but that wouldn't make a
very good
> exercise.  This implementation follows as closely as possible the AES
(FIPS 197)
> standard <http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf>.
>
> Many thanks,
> Gabriel
>
> ! Copyright (C) 2013 Gabriel Kerneis
> ! See http://factorcode.org/license.txt for BSD license.
> USING: kernel sequences grouping math math.order math.parser math.bitwise
> math.bits strings locals arrays make crypto.aes tools.test ;
> IN: fips197
>
> ! Words are represented as arrays of 4 bytes.
> ! A representation based on uint32 would certainly be more
> ! efficient, but [shift-rows] would need significant changes.
>
> : sub-word ( word -- word )
>     [ sbox nth ] map ;
>
> : rot-word ( word n -- word )
>      cut-slice prepend ;
>
> : xor-word ( word word -- word )
>     [ bitxor ] 2map ;
>
> : key-step ( key rcon -- next-key )
>     { 0 0 0 } swap prefix
>     over last 1 rot-word sub-word
>     xor-word
>     [ xor-word ] accumulate swap suffix 1 tail ;
>
> : expand-key ( key -- round-keys )
>     ! XXX rcon is broken in crypto.aes, missing last round;
>     ! let's build directly the values we need here
>     11 0 <array> 0x01 [ drop xtime ] accumulate nip swap
>     [ key-step ] accumulate nip ;
>
> : sub-bytes ( state -- state )
>     [ sub-word ] map ;
>
> : shift-rows ( state -- state )
>     flip 4 iota [ rot-word ] 2map flip ;
>
> ! See FIPS 4.2.1 for the details -- this is very inefficient,
> ! the same operations are performed many times.  Fast exponentiation
> ! should be doable with accumulate or produce, instead of map-index.
>
> : nxtime ( x y -- x' )
>     make-bits
>     [ [ xtime ] times 0 ? ] with map-index
>     0 [ bitxor ] reduce ;
>
> : word-product ( word word -- byte )
>     [ nxtime ] 2map
>     0 [ bitxor ] reduce ;
>
> : matrix-product ( word matrix -- word )
>     [ word-product ] with map ;
>
> : mix-column ( word -- word )
>     { { 2 3 1 1 }
>       { 1 2 3 1 }
>       { 1 1 2 3 }
>       { 3 1 1 2 } } matrix-product ;
>
> : mix-columns ( state -- state )
>     [ mix-column ] map ;
>
> : add-round-key ( round-key state -- state )
>     [ xor-word ] 2map ;
>
> : aes-round ( round-key state -- state )
>    sub-bytes shift-rows mix-columns add-round-key ;
>
>
> : aes-128-encrypt ( expanded-key block -- block )
>     [ unclip ] dip add-round-key
>     [ unclip-last swap ] dip
>     [ swap aes-round ] reduce
>     sub-bytes shift-rows add-round-key ;
>
> ! Inverse transformations for decrypt
>
> : inv-shift-rows ( state -- state )
>     flip { 0 3 2 1 } [ rot-word ] 2map flip ;
>
> : inv-sub-bytes ( state -- state )
>     [ [ inv-sbox nth ] map ] map ;
>
> : inv-mix-column ( word -- word )
>     { { 0xe 0xb 0xd 0x9 }
>       { 0x9 0xe 0xb 0xd }
>       { 0xd 0x9 0xe 0xb }
>       { 0xb 0xd 0x9 0xe } } matrix-product ;
>
> : inv-mix-columns ( state -- state )
>     [ inv-mix-column ] map ;
>
> : inv-aes-round ( round-key state -- state )
>    inv-shift-rows inv-sub-bytes add-round-key inv-mix-columns ;
>
> : aes-128-decrypt ( expanded-key block -- block )
>     [ reverse ] dip
>     [ unclip ] dip add-round-key
>     [ unclip-last swap ] dip
>     [ swap inv-aes-round ] reduce
>     inv-shift-rows inv-sub-bytes add-round-key ;
>
> ! Example use: decrypt some AES ECB string
> ! XXX Do not use for real-world code; ECB mode is NOT secure.
>
> : cut-padding ( seq -- seq )
>     dup last head* ;
>
> : aes-128-ecb-decrypt ( key cipher -- cleartext )
>     [ 4 group expand-key ] dip
>     2 [ 4 group ] times
>     [ aes-128-decrypt ] with map
>     concat concat
>     cut-padding ;
>
> ! I also have some unit tests, not shown here.
>
>
>
------------------------------------------------------------------------------
> Try New Relic Now & We'll Send You this Cool Shirt
> New Relic is the only SaaS-based application performance monitoring
service
> that delivers powerful full stack analytics. Optimize and monitor your
> browser, app, & servers with just a few lines of code. Try New Relic
> and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_may
> _______________________________________________
> Factor-talk mailing list
> Factor-talk@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/factor-talk
------------------------------------------------------------------------------
Try New Relic Now & We'll Send You this Cool Shirt
New Relic is the only SaaS-based application performance monitoring service 
that delivers powerful full stack analytics. Optimize and monitor your
browser, app, & servers with just a few lines of code. Try New Relic
and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_may
_______________________________________________
Factor-talk mailing list
Factor-talk@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/factor-talk

Reply via email to