LASH

n=640, m=40の圧縮関数だけ作ってみた.
Pollardの疑似乱数生成法を用いる. 底を2^{32}-1にして初期値54321で. P(i)=\begin{case} 54321&(i=0)\\ (P(i-1))^2+2\bmod{2^{32}-1}&(i>0)\end{case}.
さて, Hという行列を以下で構成する. h=(P(0),...,P(n-1))^Tとしてhの巡回行列を作る. その上部分のm行だけ取り出して各要素をZ_{256}に入れたm×n行列がH.
r, sを8mビット文字列とする. 8mビットを8ビットずつに切ってZ_{256}要素のm次元ベクトルと考える関数をgとする.
すると, 基本圧縮関数は以下.
f(r,s)=(g(r)\,\mathrm{xor\,} g(s))+H(r||s)^T.
出力はZ_{256}要素のm次ベクトル.

(use srfi-1)
(use gauche.sequence)

(define n 640)
(define m 40)
(define (sq i) (* i i))
(define P-PRG ;Pollard's PRG y_0=54321
  (let1
   tab (make-hash-table 'equal?)
   (define (memo n v) (hash-table-put! tab n v) v)
   (lambda (n)
     (cond [(zero? n) 54321]
           [(hash-table-get tab n #f)]
           [else
           (memo n
                 (modulo (+ (sq (P-PRG (- n 1))) 2)
                         (- #x80000000 1)))]))))
(define H-list-x (map P-PRG (iota n)))
(define H-list-o (map (lambda (i) (modulo i #x100)) H-list-x))
(define doubled-H-list-o (append H-list-o H-list-o))

(define (num->list-o t) ;t \in {0,1}^{8m} -> (255 0 ... 1) (m)
  (let loop [(c t) (cl '()) (i m)]
    (if (zero? i) cl
      (loop (ash c -8) (cons (bit-field c 0 8) cl) (- i 1)))))

(define (num->list-b t) ;t \in {0,1}^{8m} -> (0 0 ... 1) (8m)
  (let loop [(c t) (cl '()) (i (* 8 m))]
    (if (zero? i) cl
      (loop (ash c -1) (cons (bit-field c 0 1) cl) (- i 1)))))

(define (matrix-mul-by-H x)
  (let loop [(t (make-list m 0)) (c x) (i 0)]
    (cond [(= i n) t]
          [(= (car c) 0)
           (loop t (cdr c) (+ i 1))]
          [else
           (loop (map (lambda (a b) (modulo (+ a b) 256))
                      t
                      (subseq doubled-H-list-o (- n i) (- (+ n (* 8 m)) i)))
             (cdr c) (+ i 1))])))

(define (LASH r s) ;r,s \in {0,1}^{8m}
  (map
   (lambda (t_i h_i) (modulo (+ t_i h_i) #x100))
   (num->list-o (logxor r s))
   (matrix-mul-by-H (append (num->list-b r) (num->list-b s)))))

;(LASH 0 0)->(0 0 ... 0)
;(LASH (lognot 0) (lognot 0))->(169 169 ... 169)
;(LASH #xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa #xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)
;->(144 138 109 25 252 7 32 211 245 83 132 187 52 116 42 133 146 212 75 133 105 218 11 15 36 82 96 241 134 67 199 182 132 208 55 103 182 203 190 76)
;(LASH #x5555555555555555555555555555555555555555 #x5555555555555555555555555555555555555555)
;->(80 144 138 109 25 252 7 32 211 245 83 132 187 52 116 42 133 146 212 75 133 105 218 11 15 36 82 96 241 134 67 199 182 132 208 55 103 182 203 190)

ようやくlet loop ...という構文を理解した.
(LASH 0 0)とすると00...0という640ビットの文字列を圧縮する. (LASH (lognot 0) (lognot 0))で11...1という640ビットの文字列の場合. Pollard's PRGで640個生成して全部足すと169になるので, ハッシュ値が169を要素とする40次元ベクトルになると.

追記. SWIFFTに載っていた攻撃法は単純. 行列Hを作るときに使ったhの各要素の和が0になる確率は1/256. もしこれが起きると, 00...0と11...1を圧縮したものがともに0になる. 0101...0101と1010...1010を圧縮したものが衝突する確率も1/256.
ただし, パラメータ設定上衝突はしない. 具体的にそうならないと分かっているので, これを攻撃法と読んで良いものかどうか.