473,785 Members | 3,417 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Pure Python hashcash implementation

I decided to write a pure Python hashcash implementation. I have seen
David McNab's Python implementation. Unfortunately, as near as I can
tell (which is supported on the hashcash mailing list archive), McNab
actually implements a different algorithm than hashcash. It might (or
might not) be equivalent in security; but I cannot see any directly
way to transform what he computes into an actual hashcash stamp.

Barnes Connelly also posted a sort-of hashcash implementation on
c.l.py. But his only creates a padding suffix, not the actual
hashcash field; moreover, Connelly's version seems to look for
trailing zeros in the hash, not leading zeros.

I created a Pure Python module today that seems to conform with the
hashcash v.1 standard. But I probably missed something. It's just
barely tested--call this an alpha version. Still, I figured I'd send
it out here.... if anyone sees something I've done wrong, please let
me know so I can correct it before distributing the module more
widely.

Btw. If anyone wants to, please feel encouraged to post this to the
Cookbook.

-----------------------------------------------------------
"""Implemen t Hashcash version 1 protocol in Python

Double spend database not implemented in this module, but stub
for callbacks is provided in the 'check()' function

The function 'check()' will validate hashcash v.1 tokens, as well as
'generalized hashcash' tokens generically. Future protocol version
are
treated as generalized tokens (should a future version be published
w/o
this module being correspondingly updated).

A 'generalized hashcash' is implemented in the '_mint()' function,
with the
public function 'mint()' providing a wrapper for actual hashcash
protocol.
The generalized form simply finds a suffix that creates zero bits in
the
hash of the string concatenating 'challenge' and 'suffix' without
specifying
any particular fields or delimiters in 'challenge'. E.g., you might
get:
from hashcash import mint, _mint
mint('foo', bits=16) '1:16:040922:fo o::+ArSrtKd:164 b3' _mint('foo', bits=16) '9591' from sha import sha
sha('foo9591'). hexdigest() '0000de4c9b27ce c9b20e2094785c1 c58eaf23948' sha('1:16:04092 2:foo::+ArSrtKd :164b3').hexdig est() '0000a9fe0c6db2 efcbcab15157735 e77c0877f34'

Notice that '_mint()' behaves deterministical ly, finding the same
suffix
every time it is passed the same arguments. 'mint()' incorporates a
random
salt in stamps (as per the hashcash v.1 protocol).
"""
import sys
from string import ascii_letters
from math import ceil, floor
from sha import sha
from random import choice
from time import strftime, localtime, time

ERR = sys.stderr # Destination for error messages
DAYS = 60 * 60 * 24 # Seconds in a day

def mint(resource, bits=20, now=None, ext='', saltchars=8,
stamp_seconds=F alse):
"""Mint a new hashcash stamp for 'resource' with 'bits' of
collision

20 bits of collision is the default.

'ext' lets you add your own extensions to a minted stamp. Specify
an
extension as a string of form 'name1=2,3;name 2;name3=var1=2, 2,val'
FWIW, urllib.urlencod e(dct).replace( '&',';') comes close to the
hashcash extension format.

'saltchars' specifies the length of the salt used; this version
defaults
8 chars, rather than the C version's 16 chars. This still
provides about
17 million salts per resource, per timestamp, before birthday
paradox
collisions occur. Really paranoid users can use a larger salt
though.

'stamp_seconds' lets you add the option time elements to the
datestamp.
If you want more than just day, you get all the way down to
seconds,
even though the spec also allows hours/minutes without seconds.
"""
ver = "1"
now = now or time()
if stamp_seconds: ts = strftime("%y%m% d%H%M%S", localtime(now))
else: ts = strftime("%y%m% d", localtime(now))
challenge = "%s:"*6 % (ver, bits, ts, resource, ext,
_salt(saltchars ))
return challenge + _mint(challenge , bits)

def _salt(l):
"Return a random string of length 'l'"
alphabet = ascii_letters + "+/="
return ''.join([choice(alphabet ) for _ in [None]*l])

def _mint(challenge , bits):
"""Answer a 'generalized hashcash' challenge'

Hashcash requires stamps of form
'ver:bits:date: res:ext:rand:co unter'
This internal function accepts a generalized prefix 'challenge',
and returns only a suffix that produces the requested SHA leading
zeros.

NOTE: Number of requested bits is rounded up to the nearest
multiple of 4
"""
prefix_hash = sha(challenge)
counter = 0
hex_digits = int(ceil(bits/4.))
while 1:
candidate = prefix_hash.cop y()
candidate.updat e(hex(counter)[2:])
digest = candidate.hexdi gest()
if digest.startswi th('0'*hex_digi ts):
return hex(counter)[2:]
counter += 1

def check(stamp, resource=None, bits=None,
check_expiratio n=None, ds_callback=Non e):
"""Check whether a stamp is valid

Optionally, the stamp may be checked for a specific resource,
and/or
it may require a minimum bit value, and/or it may be checked for
expiration, and/or it may be checked for double spending.

If 'check_expirati on' is specified, it should contain the number
of
seconds old a date field may be. Indicating days might be easier
in
many cases, e.g.
from hashcash import DAYS
check(stamp, check_expiratio n=28*DAYS)


NOTE: Every valid (version 1) stamp must meet its claimed bit
value
NOTE: Check floor of 4-bit multiples (overly permissive in
acceptance)
"""
if stamp.startswit h('0:'): # Version 0
try:
date, res, suffix = stamp[2:].split(':')
except ValueError:
ERR.write("Malf ormed version 0 hashcash stamp!\n")
return False
if resource is not None and resource != res:
return False
elif check_expiratio n is not None:
good_until = strftime("%y%m% d%H%M%S",
localtime(time( )-check_expiratio n))
if date < good_until:
return False
elif callable(ds_cal lback) and ds_callback(sta mp):
return False
elif type(bits) is not int:
return True
else:
hex_digits = int(floor(bits/4))
return sha(stamp).hexd igest().startsw ith('0'*hex_dig its)
elif stamp.startswit h('1:'): # Version 1
try:
claim, date, res, ext, rand, counter =
stamp[2:].split(':')
except ValueError:
ERR.write("Malf ormed version 1 hashcash stamp!\n")
return False
if resource is not None and resource != res:
return False
elif type(bits) is int and bits > int(claim):
return False
elif check_expiratio n is not None:
good_until = strftime("%y%m% d%H%M%S",
localtime(time( )-check_expiratio n))
if date < good_until:
return False
elif callable(ds_cal lback) and ds_callback(sta mp):
return False
else:
hex_digits = int(floor(int(c laim)/4))
return sha(stamp).hexd igest().startsw ith('0'*hex_dig its)
else: # Unknown ver or generalized
hashcash
ERR.write("Unkn own hashcash version: Minimal
authentication! \n")
if type(bits) is not int:
return True
elif resource is not None and stamp.find(reso urce) < 0:
return False
else:
hex_digits = int(floor(bits/4))
return sha(stamp).hexd igest().startsw ith('0'*hex_dig its)

def is_doublespent( stamp):
"""Placehol der for double spending callback function

The check() function may accept a 'ds_callback' argument, e.g.
check(stamp, "me***@gnosis.c x", bits=20,
ds_callback=is_ doublespent)

This placeholder simply reports stamps as not being double spent.
"""
return False
Jul 18 '05 #1
1 2515
Well, following up on myself. I sped up my implementation by about
40%, added some more documentation, and added command-line switches
that more-or-less match the C hashcash utility. The new one is still
alpha level, but it will have a permanent URL at:

http://www.gnosis.cx/download/gnosis/util/hashcash.py

As the URL insinuates, I'll included this in a future release of
Gnosis Utilities (under the subpackage indicated by the directory).
But I haven't done that yet (I think I have some other old
user-recommended changes to dig through before doing a new release).

Still, being alpha and all, I would be thrilled to get suggestions or
bug reports.

Yours, David...
Jul 18 '05 #2

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
5656
by: andrew.fabbro | last post by:
I'm looking for an implementation of AES (the Advanced Encryption Standard) in pure Python. I'm aware of pycrypto, but that uses C code. I'm hoping to find something that only uses Python...I'm willing to trade speed for portability, since my application is designed for several different platforms. Anyone know if this has been done? Thanks,
0
1024
by: Max | last post by:
I am writing a Hashcash program in python. Rather than create an email client plugin, I have done this thru a proxy server which adds the Hashcash before forwarding. What I want to know is whether this is safe. I currently use this code: class HashcashServer (smtpd.PureProxy): def process_message (self, peer, mailfrom, rcpttos, data): if peer in trusted_peers: # add Hashcash and forward
10
7315
by: Martin Vorbrodt | last post by:
Example code in one of my books intrigues me: class B { public: B* Clone() const { B* p = DoClone(); assert(typeid(*p) == typeid(*this)); return p; }
2
1981
by: Carl Cerecke | last post by:
Well, it doesn't quite rule them all, but it is fast: About three times faster than using one function per state. Faster than using generators. Faster than using code objects. Some, possibly minor, problems: 1. The generated code is ugly. 2. The generated code can be quite large, depending on the shape of the FSM (Maximum theoretical size left as an exercise for the reader ;-) 3. Not as fast as byte code hacks, or using pyrex/psyco....
4
2176
by: Akihiro KAYAMA | last post by:
Hi all. I would like to ask how I can implement string-like class using tuple or list. Does anyone know about some example codes of pure python implementation of string-like class? Because I am trying to use Python for a text processing which is composed of a large character set. As the character set is wider than UTF-16(U+10FFFF), I can't use Python's native unicode string class.
2
1784
by: Rob McMullen | last post by:
Wheel reinvention preemption question: is there an existing pure- python library with functionality similar to KDE's kio/kioslave implementation? A multi-protocol, extensible library based on URLs that abstracts directory listing and file read/write? I'm looking to use it in client code, not server, so it doesn't have to be asynchronous like kio; ideally it would be small and only depend on the standard python library. Here's what I'm...
12
3141
by: betabrain.honshu | last post by:
Hi Folks, for those of you who are familiar with the micropledge.com project, here is a good opportunity to spend or earn something: http://micropledge.com/projects/pysalsa20 I know that the details of this project are still a bit unclear, but that is something we could discuss. By the way, the end result should look like it's a part of the python standard library (naming conventions, etc.) and of course it will be open source.
14
2757
by: Jack | last post by:
Hi, I meet a question with it , I did not get clear the different betteen them, for example: #include <iostream>
8
1584
by: Roy Smith | last post by:
Does there exist a pure Python version of a MySQL module? I've got a data logging application that needs to run on a whole bunch of OSs, ranging from Windows to a dozen different unix flavors on all sorts of hardware. Portability is much more important than performance for this application. We're only inserting a few hundred records a day from each system, but the ability to quickly deploy to anywhere I've already got Python running is...
0
10315
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
10085
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9947
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8968
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7494
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6737
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5379
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5511
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
3
2877
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.