summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Andreas Benkard <code@mail.matthias.benkard.de>2012-02-23 11:12:47 +0100
committerMatthias Andreas Benkard <code@mail.matthias.benkard.de>2012-02-23 11:12:47 +0100
commit5b1507b89b3c688cf92a6c303ec0bf7d5648309a (patch)
treed357b0d5eb082950e0d86fdb46fe066691596050
parentccf332ebbce0cb266aa84dea08bca8ce6182ae9e (diff)
Commit the dormant Threefish implementation.
-rw-r--r--cubehash.rkt4
-rw-r--r--threefish.rkt132
2 files changed, 97 insertions, 39 deletions
diff --git a/cubehash.rkt b/cubehash.rkt
index 3aed1f3..9eb8a84 100644
--- a/cubehash.rkt
+++ b/cubehash.rkt
@@ -61,8 +61,8 @@
(define (cubehash init-rounds rounds/block block-size fin-rounds output-bits)
- (λ: ([msg : Bytes])
- (let*: ([state : (Vectorof Word)
+ (λ: ([msg : Bytes])
+ (let*: ([state : (Vectorof Word)
(make-vector 32 #x0)]
[msg-pad : Bytes
(bytes-append msg
diff --git a/threefish.rkt b/threefish.rkt
index f09ef4c..a9cd8d0 100644
--- a/threefish.rkt
+++ b/threefish.rkt
@@ -19,7 +19,7 @@
(require "util.rkt")
-(provide: [threefish (Bytes Bytes Bytes -> Bytes)])
+(provide: [threefish (Bytes Bytes Bytes (U 'encrypt 'decrypt) -> Bytes)])
(define-type Long Exact-Nonnegative-Integer)
@@ -27,6 +27,10 @@
(define (l+ a b)
(bitwise-and (+ a b) #xffffffffffffffff))
+(: l- (Long Long -> Long))
+(define (l- a b)
+ (bitwise-and (- a b) #xffffffffffffffff))
+
(: lxor (Long Long -> Long))
(define lxor bitwise-xor)
@@ -36,7 +40,14 @@
(bitwise-ior (bitwise-and ash #xffffffffffffffff)
(arithmetic-shift ash -64))))
-(define (threefish key tweak plaintext)
+(: rrot (Long Exact-Nonnegative-Integer -> Long))
+(define (rrot a e)
+ (bitwise-ior (arithmetic-shift a (- 64 e))
+ (arithmetic-shift a (- e))))
+
+(define (threefish key tweak plaintext mode)
+ (assert (= (bytes-length key) (bytes-length plaintext)))
+ (assert (= (bytes-length tweak) 16))
(let*: ([size (bytes-length key)]
[words (quotient size 8)]
[rounds (case size
@@ -48,7 +59,7 @@
[(32) #(0 3 2 1)]
[(64) #(2 1 4 7 6 5 0 3)]
[(128) #(0 9 2 13 6 11 4 15 10 7 12 3 14 5 8 1)]
- [else (error "Invalid key size")])]
+ [else (error "Invalid key size")])]
[mixbox : (Vectorof (Vectorof Long))
(case size
[(32) #(#( 5 56)
@@ -58,7 +69,25 @@
#(26 20)
#(53 35)
#(11 42)
- #(59 50))]
+ #(59 50))
+ #;
+ #(#(14 16)
+ #(52 57)
+ #(23 40)
+ #( 5 37)
+ #(25 33)
+ #(46 12)
+ #(58 22)
+ #(32 32))
+ #;
+ #(#(32 32)
+ #(58 22)
+ #(46 12)
+ #(25 33)
+ #( 5 37)
+ #(23 40)
+ #(52 57)
+ #(14 16))]
[(64) #(#(38 30 50 53)
#(48 20 43 31)
#(34 14 15 27)
@@ -77,33 +106,45 @@
#(47 49 27 58 37 48 53 56))]
[else (error "Invalid key size")])]
[mix
- (λ: ([d : Integer] [j : Integer] [x0 : Long] [x1 : Long])
- (let*: ([y0 : Long (l+ x0 x1)]
- [y1 : Long
- (lxor (lrot x1
- (vector-ref (vector-ref mixbox (modulo d 8))
- j))
- y0)])
- (values y0 y1)))]
+ (lambda: ([d : Integer] [j : Integer] [x0 : Long] [x1 : Long])
+ (let ([rotnum (vector-ref (vector-ref mixbox (if (eq? mode 'encrypt)
+ (modulo d 8)
+ (- 8 (modulo d 8))))
+ j)])
+ (if (eq? mode 'encrypt)
+ (let*: ([y0 : Long
+ (l+ x0 x1)]
+ [y1 : Long
+ (lxor (lrot x1 rotnum)
+ y0)])
+ (values y0 y1))
+ (let*: ([y1 : Long
+ (rrot (lxor x0 x1)
+ rotnum)]
+ [y0 : Long
+ (l- x0 y1)])
+ (values y0 y1)))))]
[words->bytes
: ((Vectorof Long) -> Bytes)
- (λ (v)
+ (lambda (v)
(bytes-append*
(reverse
(for/fold: ([blocks : (Listof Bytes) '()])
- ([i : Exact-Nonnegative-Integer (in-range words)])
+ ([i : Exact-Nonnegative-Integer (in-range (vector-length v))])
(cons (integer->bytes/size (vector-ref v i) 'little-endian 8)
blocks)))))]
[bytes->word-list
: (Bytes -> (Listof Long))
- (λ (b)
+ (lambda (b)
(for/fold: ([words : (Listof Long) '()])
- ([i : Exact-Nonnegative-Integer (in-range words)])
+ ([i : Exact-Nonnegative-Integer (in-range (quotient
+ (bytes-length b)
+ 8))])
(cons (bytes->integer/le (subbytes b (* i 8) (* (add1 i) 8)))
words)))]
[bytes->words
: (Bytes -> (Vectorof Long))
- (λ (b)
+ (lambda (b)
(list->vector (reverse (bytes->word-list b))))]
[key-words : (Vectorof Long)
(let ([ks (bytes->word-list key)])
@@ -113,41 +154,49 @@
(foldl lxor (quotient (expt 2 64) 3) ks)
ks))))]
[tweak-words : (Vectorof Long)
- (let ([t0 (bytes->integer/le (subbytes key 0 8))]
- [t1 (bytes->integer/le (subbytes key 8 16))])
+ (let ([t0 (bytes->integer/le (subbytes tweak 0 8))]
+ [t1 (bytes->integer/le (subbytes tweak 8 16))])
(vector t0 t1 (lxor t0 t1)))]
[key-schedule
: (Long Long -> Long)
;; XXX memoize?
- (λ: ([s : Long] [i : Long])
+ (lambda: ([s : Long] [i : Long])
(let ([k (vector-ref key-words (modulo (l+ s i) (l+ words 1)))])
- (cond
- [(= i (- words 1))
- (l+ k s)]
- [(= i (- words 2))
- (l+ k (vector-ref tweak-words (modulo (l+ s 1) 3)))]
- [(= i (- words 3))
- (l+ k (vector-ref tweak-words (modulo s 3)))]
- [else
- k])))]
+ (assert (< i words))
+ (l+ k
+ (cond
+ [(= i (- words 1))
+ s]
+ [(= i (- words 2))
+ (vector-ref tweak-words (modulo (l+ s 1) 3))]
+ [(= i (- words 3))
+ (vector-ref tweak-words (modulo s 3))]
+ [else
+ 0]))))]
[make-subkey
: (Long -> (Vectorof Long))
- (λ: ([s : Long])
+ (lambda: ([s : Long])
(list->vector
(reverse
(for/fold: ([words : (Listof Long) '()])
([i : Exact-Nonnegative-Integer (in-range words)])
(cons (key-schedule s i) words)))))]
[state (bytes->words plaintext)])
+ (printf "size: ~a, words: ~a, rounds: ~a~%" size words rounds)
(for: ([round : Exact-Nonnegative-Integer (in-range rounds)])
+ (printf "Round ~a: ~s~%" round (words->bytes state))
+ ;;(printf ".")
(let: ([e
: (Vectorof Long)
(if (zero? (modulo round 4))
- (vector-map l+
+ (begin ;;(printf "PLUS!\n")
+ (vector-map l+
state
(make-subkey (quotient round 4)))
+ )
(vector-copy state))])
- (for: ([j : Exact-Nonnegative-Integer (in-range (quotient words 2))])
+ (for: ([j : Exact-Nonnegative-Integer (in-range (quotient words 2))])
+ ;;(printf "Mix.\n")
(let-values ([(f0 f1)
(mix round
j
@@ -155,11 +204,20 @@
(vector-ref e (add1 (* 2 j))))])
(vector-set! e (* 2 j) f0)
(vector-set! e (add1 (* 2 j)) f1)))
+ ;;(printf "~s~%" (words->bytes e))
(for: ([i : Exact-Nonnegative-Integer (in-range words)])
+ ;;(printf "Permute.\n")
(vector-set! state i (vector-ref e (vector-ref pbox i))))))
- (for: ([i : Exact-Nonnegative-Integer (in-range words)])
- (vector-set! state
- i
- (l+ (vector-ref state i)
- (key-schedule (quotient rounds 4) i))))
+ (vector-map! l+ state (make-subkey (quotient rounds 4)))
+ ;;(vector-map! lxor state (bytes->words plaintext))
+ (vector-map (lambda (x) (printf "~x " x)) state)
(words->bytes state)))
+
+;;; Test vector from the PySkein documentation.
+(threefish #"key of 32,64 or 128 bytes length"
+ ;;(integer->bytes/size #x00 'big-endian 32)
+ ;;(integer->bytes/size #x00 'big-endian 8)
+ ;;(integer->bytes/size #x00 'big-endian 32)
+ #"tweak: 16 bytes "
+ #"block of data,same length as key"
+ 'encrypt)