From dedb1d753660d719bf9b3924179359b2458765f6 Mon Sep 17 00:00:00 2001 From: Diego Martinelli Date: Sat, 9 May 2009 17:23:41 +0200 Subject: [PATCH] Main implementation done. Need docs and tests. --- extra/hashcash/authors.txt | 1 + extra/hashcash/hashcash.factor | 90 +++++++++++++++++++++++++++++++++- 2 files changed, 89 insertions(+), 2 deletions(-) diff --git a/extra/hashcash/authors.txt b/extra/hashcash/authors.txt index e69de29bb2..f6e3b59c4c 100755 --- a/extra/hashcash/authors.txt +++ b/extra/hashcash/authors.txt @@ -0,0 +1 @@ +Diego Martinelli diff --git a/extra/hashcash/hashcash.factor b/extra/hashcash/hashcash.factor index fe7cf10bd3..3e75aad94c 100755 --- a/extra/hashcash/hashcash.factor +++ b/extra/hashcash/hashcash.factor @@ -1,4 +1,90 @@ -! Copyright (C) 2009 Your name. +! Copyright (C) 2009 Diego Martinelli. ! See http://factorcode.org/license.txt for BSD license. -USING: ; +USING: accessors byte-arrays calendar calendar.format +checksums checksums.openssl classes.tuple +fry kernel make math math.functions math.parser math.ranges +present random sequences splitting strings syntax ; IN: hashcash + +! Hashcash implementation +! Reference materials listed below: +! +! http://hashcash.org +! http://en.wikipedia.org/wiki/Hashcash +! http://www.ibm.com/developerworks/linux/library/l-hashcash.html?ca=dgr-lnxw01HashCash +! +! And the reference implementation (in python): +! http://www.gnosis.cx/download/gnosis/util/hashcash.py + +> 100 mod pad-00 ] + [ month>> pad-00 ] + [ day>> pad-00 ] tri 3append ; + +! Random salt is formed by ascii characters +! between 33 and 126 +: available-chars ( -- seq ) + 33 126 [a,b] [ CHAR: : = not ] filter ; + +PRIVATE> + +! Generate a 'length' long random salt +: salt ( length -- salted ) + available-chars '[ _ random ] "" replicate-as ; + +TUPLE: hashcash version bits date resource ext salt suffix ; + +: ( -- tuple ) + hashcash new + 1 >>version + 20 >>bits + get-date >>date + 8 salt >>salt ; + +M: hashcash string>> + tuple-slots [ present ] map ":" join ; + +hex >>suffix ; + +: get-bits ( bytes -- str ) + [ >bin 8 CHAR: 0 pad-head ] { } map-as concat ; + +: checksummed-bits ( tuple -- relevant-bits ) + dup string>> sha1-checksum + swap bits>> 8 / ceiling head get-bits ; + +: all-char-zero? ( seq -- ? ) + [ CHAR: 0 = ] all? ; inline + +: valid-guess? ( checksum tuple -- ? ) + bits>> head all-char-zero? ; + +: (mint) ( tuple counter -- tuple ) + 2dup set-suffix checksummed-bits pick + valid-guess? [ drop ] [ 1+ (mint) ] if ; + +PRIVATE> + +: mint* ( tuple -- str ) + 0 (mint) string>> ; + +: mint ( resource -- str ) + + swap >>resource + mint* ; + +! One might wanna add check based on the date, +! passing a 'good-until' duration param +: check-stamp ( stamp -- ? ) + dup ":" split [ sha1-checksum get-bits ] dip + second string>number head all-char-zero? ; + -- 2.34.1