Example!

This is the output after running ballot.pl, the program that generates the anonymous signed ballot number. This program connects to a "blind signature server", implemented by the blindsigd program.

To give a better view what is going on, debugging info is left in place. All communication to and from the server is given. Lines that start with < are received from the server, lines that start with > are sent by the client to the server.

pc:~ $ ./ballot.pl 
Connected to 127.0.0.1:12345
< 200-blindsigd
< 200-My public key is:
< 200-n: 1338766706758802710999691544752765123386033311665063296003991\
<     3819892446022801746583281753027051219182124706796665947152168022\
<     1000977337887008203534881016995518198422789776489392399873978565\
<     6086486092385869127221042652411082985928400370600714339199749329\
<     3024806847269257987646160822301006444946883139874501513
< 200-e: 34381
< 200-Please RSA encode your credentials!
< 200 Challenge: 671043708
Server "fingerprint" is b05e04eb
Please log in to obtain your anonymous ticket
Login: johnpc
Password: foo
> IAM 5679085053281102477963184866530582033345517668013900641096823101\
    5380249404977965566512572312110884661463023430147487419829105564\
    5117224206211818078123020080039872002656941653087980814719062376\
    2429153400814281965678403428584288263080729566738549983494784826\
    352244953814081183600463109133797788469730523666244

The above number is the string "671043708 johnpc:foo" converted to a number by treating the bytes in the string as a very long big endian binary number, and then rsa-encoding it using the server's public key.

That string converts to 0x363731303433373038206A6F686E70633A666F6F or to 309516327515356569311957416647941778148317097839 decimal.

< 200 Welcome, Jan-Pieter Cornet
> BLINDSIG
< 201-10 blinded messages should be sent
< 201-Message format should be:
< 201 (?i-xsm:^Ballot number: [0-9A-F]{16}$)

We initiate the blind signature protocol, by giving the "BLINDSIG" command to the server. The server responds by stating that it expects 10 messages, and what message format it expects.

The reason we're not signing just any number the client made up, is that this opens up an insecurity in the RSA algorithm, see Applied Cryptography, chapter 12.4, "Chosen Ciphertext Attack Against RSA" (page 286-287 in my edition).

We commence the protocol by giving 10 blinded messages:

> 82531202765220029568999868220435619693943842358102192714536543785408\
    7875884296863022884732180644011031405696462786405876304483672813\
    4759541171579623415665195967076575386148191572968381194004422231\
    0759924729290574420579866649464920242415916425082027571259521660\
    15647681437967780851303328413308580728471889744
> 10843162697525143811199221720193724250674942056695196575235261488597\
    1515906819786469522467706639709154696725232686775345966760139137\
    2726938896302772814336360748980715136036032184542964963271125175\
    8550230656573850284461678776494412387652509621445233612065844162\
    749452687301813823238583369619024486529400443831
> 26513765185669089526987051458082659731041797961598920368936735472258\
    0289806923990584155997892243980399951095331482212479943995158224\
    8741418988985595235555854428415170079670490592690539486104180343\
    6446903791127366201980563761469608611857281569090820035072466877\
    73771167862527886817598325656148474839095989483
> 88654313730513379342910988468663858673691642840816946503687979802450\
    2935256676277828860329676325670694566433019419128739468017735892\
    3645295858800109579355009603024745817303430820971848832930018428\
    3892814852267150831465753054588827606469331030714392246755369838\
    46244043601387479358764390212549596188800450395
> 87829078070456272417395262528025426994012691800794750980657833244396\
    1251607859259559855224212834026295553498754377447629646122009319\
    3421725130860381378933078902580791856994084463880729030589267487\
    9046822290612180521440088281681293788422141095364574779702591027\
    33473616107885603199382143416623543223998933971
> 11135937112628987193289045507859891014713345823426409116356117801986\
    0341375845999658522885901613300586454318910893300619386785292570\
    7319483855577958428412027318229921387347629545863508991304958344\
    0424925847690737473371343432903855063978104585465544157134017878\
    858344093439131014684027337072718252158332509218
> 62201303335866883654794436210174207322374655936364254470841848098848\
    3826326663751114928759498856698277085834157798003269639857973278\
    4839374510855579224263690026691450039588085092282511556733260252\
    6134299710852602119711050166527235933161480512859510117579080139\
    40961633801392075532503862973156886209515961887
> 49802075028635855873605541865421451106992268093033609943641121750948\
    8216199573432991736247852834932021857382517194881940927402758675\
    2224987485209379856853503419361683631299447947070249086954712627\
    6656612324165301521109125324974018825421481427369993922977215286\
    51724292654343895948780351952940312680094800517
> 48515069333288933241788127117793042728096179422870010679659982868911\
    0851213360551900687554090840505660401166532628798503798330187939\
    3798909068374667518674520160262274376520960692654796281641030134\
    7757232540346852358827153013857747357041835573814771011241915433\
    41672362396215550513425868174336026830973561835
> 81028931581234932593508748186087632542516343902027188746874360833470\
    0991688341640569050140905190738852663303599530275305569042036654\
    7021186979087030670429883138518266714438977262782008465242082848\
    7748143655421898843153683757556646124298637894927193695785296482\
    80248245389513347648789789894866340606102574982
< 202-Thank you. This was the point of no return.
< 202-I will sign this message: 8
< 202 Give me all other unblinding factors

After receiving the 10 messages, the server tells us it will sign message number 8 (with offset 0, ie. the first message is message number 0!). We send all the other unblinding factors to the server.

Note that we send the number with which we multiplied the messages, so to unblind them, the server first has to calculate the inverse (mod n) of the given factors. This is done because calculating the inverse is an expensive operation, and we are sure the server uses a fast library (Math::GMP), but the client might be using a slow library (Math::BigInt), and calculating 9 inverses in the client might make it prohibitively slow.

> 11208989439952217224466966219073438611947450951613071686885517854851\
    9647063405022845474085548710513952564735981511418098190066718333\
    4768568722385923161452141039633377324276704336875151510883517025\
    9006187716762124094041396497415811794709673043343650105653407452\
    636368717713347041175671663970860639689742892514

To give a little more insight into the protocol... the first (0th) message that the client sent, was "Ballot number: a99147ec1e49f354", blinded with the blinding factor above. That string corresponds to the hexadecimal number: 0x42616C6C6F74206E756D6265723A2061393931343765633165343966333534, or to the decimal number: 117284298764828962767645287810547745901604755097894472863392160161195046196.

If you multiply that by the blinding factor above (mod n), you'll get the first message sent by the client.

We continue with the other unblinding factors...

> 88291465383812556581007457399511052502502493656757937305142385609029\
    1683863785482856793122748209527283037159922923265171436552990218\
    4526434417892433040864753697100741183509406994241687438776645581\
    6339427835867143820643613847863660396837484631681526019675805581\
    64043972008612941976685473972802272050554832977
> 97229014637689994110274550644490032131945322373159242466667073091693\
    2113455468980157280459632730334481187814206771224967992870721614\
    3083222118162322028000344453316370547188233526430500019575757340\
    5345479722831442649599128484135314230451939062347301890902291558\
    6084984116545910694750338803413645525189216516
> 56592129592805969691447105612289868430540214479720351619083076136026\
    7813939769299521903104639471018783218250516640766217883117034644\
    6365270934453037281517197384811678959614218869300815199783939327\
    1916318972549165795991118956017851126848611980455341245978117634\
    40941868853266291701930342855194637795495471965
> 10728410654229546200307126619733339332752918554507932740494603681992\
    8827459644338933270049397358770077879049405057951849084430818787\
    0251269880122168355601926085566830549100984090328295764460412076\
    3259322437082333509433355586991550844470943624027173323037336626\
    605271535060901181109634407125807938104951691952
> 31050787241991150220709727437998750390870209303113092049128176693883\
    6568842886212071615294615105314351670362920287946447448068032954\
    7435098178070819267423028118469483917368443236095134358564738021\
    7266072547109205328899567148785282689268584406852020563641734517\
    48676673465314931468826002560173580973544824522
> 51522184322144399543067337171340079592769206916978554873204648697849\
    6673747548990306428984145199038780791625119370827753334266969048\
    3313032278851408318756852281866593098308790221300068423557717604\
    4175607324187439539409745705804813141226984009045130001691475506\
    64807304612298035733992867293179605942324950891
> 10316745396408102288797459132998412093730017147908763001548807432562\
    1115847749326068624336878558579947879945125616196693543499701856\
    3928789340183781486587638636030203718103106712560725669661998878\
    7486289727837530697019199928431497378275912718855921163941798960\
    551430449359578329480890523546409271014477595680
> 19907215785310363541433262853713189673213737842756280920016179785759\
    2965342411169156745757536967720537452431382154202332430433678062\
    0202021126499371632918855132720823862615426764356025168836847113\
    0437793556715769837106959553586487576237991640231610689643860436\
    29163803428237091458565430153772274352262634276

The client sent the unblinding factors for the messages 0,1,2,3,4,5,6,7 and 9 pretty fast, while the server is verifying all the messages. To give a status report, the server gives a message after verifying each message.

< 100-Message 0 OK
< 100-Message 1 OK
< 100-Message 2 OK
< 100-Message 3 OK
< 100-Message 4 OK
< 100-Message 5 OK
< 100-Message 6 OK
< 100-Message 7 OK
< 100-Message 9 OK
< 300-All OK, thanks.
< 300 Signatures follow, terminated by CRLF.CRLF
< 8: 58107422858676776081990699900441077887446556867724633003417274178\
<     1426867268823317007371158988692971878889148742466042048415056510\
<     7279772297158448409364341116670182545919948964543457530451574621\
<     6415216183121197938509605380656813721683076274104995603896138638\
<     0586941527471199451159397218636628717485732848571
< .

After verifying all signatures, the server gives us the (blinded) signature for message number 8 that we sent. The client unblinds the signature (which means the client has to calculate a modulo inverse), and then verifies the signature against the public key.

Verifying the signature simply means "decrypting" it using the public key of the server, which should give the original message. This is what the client outputs in this case:

We got a valid signature!
Ballot number: eeb75da1b0c95e23
Sig: 724083733172533988171769548783477055252537754314872614600064667\
    5079442295476720854898137109536100414642051390143993862072919730\
    8880993021407272905840311497987399266351316823878361263350988485\
    4625412714178000026007800535583940506073476562111311185828005233\
    7626008579799830874382377558065541385420553870933105
> QUIT

That concludes the protocol, and we now have a valid, signed, anonymous ballot number.

To continue, we have to do the actual vote, for example by filling in the ballot via the entervote.cgi script.