Blind signature Java code
Tuesday January 15th, 2013
Blind signature implementation in Java
Here is a client side code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 | /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package blindsignature; import java.math.BigInteger; import java.security.SecureRandom; /** * VotingClient is a client-side of blind signature voting module. * @author Pawel Maniora */ public class VotingClient { /** * number of candidates on voting cards */ private int candidates; /** * numbers of cards - the higher amount - the safer and * slower voting is. */ private int cardamount; /** * public key encriptor. everybody who wants use it to encrypt message */ private BigInteger e; /** * modulus used in encryption/decryption. everybody who wants use it */ private BigInteger mod; /** * all cards used to vote in plain format */ private BigInteger[][] cards; /** * all blind cards */ private BigInteger[][] encodedCards; /** * set of r. One r for each card used to make blinding factor */ private BigInteger[] r; /** * set of inverted r used to remove blinding factor */ private BigInteger[] rprim; /** * inverted r used to remove blinding factor from signed card * saved in another place than rprim set to send full rprim set to server */ private BigInteger rfinal; /** * card signed by private key of server */ private BigInteger[] signedCard; /** * voting client constructor */ VotingClient(int candidates, int cardamount, BigInteger e, BigInteger mod){ this.candidates = candidates; this.cardamount = cardamount; this.e = e; this.mod = mod; this.generateCards(); this.generateBlindingFactors(); this.generateUnblindingFactors(); this.encodeCards(); this.rfinal=null; this.signedCard=null; } /** * gemerate voting cards */ public final void generateCards(){ cards = new BigInteger[cardamount][candidates]; SecureRandom randomGenerator = new SecureRandom(); for (int i = 1; i <= cardamount; ++i){ //generate 9digit number int randomInt = randomGenerator.nextInt(899999999)+100000000; for (int j = 1; j <= candidates; ++j) { cards[i-1][j-1]=new BigInteger(Integer.toString(j)+Integer.toString(randomInt)); // System.out.println("Generated : " + j+randomInt); } } } /** * generate Blinding factor */ public final void generateBlindingFactors(){ r = new BigInteger[cardamount]; for (int i = 1; i <= cardamount; ++i){ BigInteger rrand = null; BigInteger gcd = null; BigInteger one = new BigInteger("1"); SecureRandom random = new SecureRandom(); //check that gcd(r,n) = 1 && r < n && r > 1 do { byte [] randomBytes = new byte[124]; random.nextBytes(randomBytes); rrand = new BigInteger(1, randomBytes); gcd = rrand.gcd(mod); //System.out.println("gcd: " + gcd); r[i-1]=rrand; } while(!gcd.equals(one) || rrand.compareTo(mod)>=0 || rrand.compareTo(one)<=0); } } /** * create rprim from r */ public final void generateUnblindingFactors(){ rprim = new BigInteger[r.length]; for (int i = 1; i <= r.length; ++i){ rprim[i-1] = r[i-1].modInverse(mod); } } /** * set final r and clear this r before send vector of requested r. */ public void setRfinal(int norequest){ if(rfinal==null && norequest>=0 && norequest <= candidates) { rfinal = rprim[norequest]; rprim[norequest] = new BigInteger("0"); } else System.out.println("ERROR: rfinal set before!"); } /** * set signed card generated by VotingServer */ public void setSignedCard(BigInteger[] signedCard){ this.signedCard = signedCard; } /** * send encodedCards to VotingServer */ public final BigInteger[][] getCodedCards(){ return encodedCards; } /** * send rprim to VotingServer */ public BigInteger[] getRprim(){ //if rfinal != null means that rfinal is set and rprim is cleaned from rfinal if(rfinal!=null){ return rprim; }else return null; } /** * encode cards to "codecards" for acceptable to send to VotingServer */ public final void encodeCards(){ encodedCards =new BigInteger[cardamount][candidates]; for (int i = 1; i <= cardamount; ++i){ for (int j = 1; j <= candidates; ++j) { BigInteger re = r[i-1].modPow(e,mod); encodedCards[i-1][j-1]=cards[i-1][j-1].multiply(re).mod(mod);//multiply(re).mod(mod); // System.out.println("Generated : " + j+randomInt); } } } /** * remove rprim from signed card */ public void decodeCard(){ for (int j = 1; j <= candidates; ++j) { signedCard[j-1]=signedCard[j-1].multiply(rfinal).mod(mod); } } /** * send vote to VotingServer * @param candidate number of candidate on wchih you voting. */ public BigInteger sendVote(int candidate){ if(signedCard!=null){ decodeCard(); return signedCard[candidate]; } else return null; } /** * inform Voter if vote is accepted or not */ public void isVoteAccepted(boolean accepted){ if(accepted){ System.out.println("GLOS ZOSTAŁ DODANY"); // add confirm information here } else { System.out.println("WYSTAPIL BLAD Z DODANIEM GLOSU!"); //add reject information here } } } |
And here is a server side code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package blindsignature; import java.math.BigInteger; /** * VotingServer is a server-side of blind signature voting module. * * @author Pawel Maniora */ public class VotingServer { /** * number of candidates on voting cards */ private int candidates; /** * numbers of cards - the higher amount - the safer and * slower voting is. */ private int cardamount; /** * private key decriptor used to sign an decrypt votes */ private BigInteger d; /** * public key encriptor. everybody who wants use it to encrypt message */ public BigInteger e; /** * modulus used in encryption/decryption. everybody who wants use it */ public BigInteger mod; /** * number of voting card which is typed to not be checked and if everything * will be ok with others to be signed */ public Integer norequest; /** * all coded cards sended from client */ private BigInteger[][] codedcards; /** * Voting Server constructor */ VotingServer(int candidates, int cardamount, BigInteger d, BigInteger e, BigInteger mod){ this.candidates = candidates; this.cardamount = cardamount; this.d = d; this.e = e; this.mod = mod; this.norequest = null; this.codedcards = null; } /** * Set Coded cards generated by client */ public void setCodedCards(BigInteger[][] codedcards) { if(this.codedcards==null) this.codedcards = codedcards; } /** * Randomly choose @see #cardamount */ public int drawNoRequest(){ if(norequest == null) norequest = (int)(Math.random()*(cardamount)); return norequest; } /** * The method check if format of cards are correct - if all without random one * are correct - it means that one left in very high probablility is also correct * * @param rprim - set of r^-1 mod(mod) used to unblind @see #codedcards */ public boolean checkCards( BigInteger[] rprim){ String cardpattern =""; for (Integer i = 1; i <= cardamount; ++i){ if(!i.equals(norequest+1)){ for (int j = 1; j <= candidates; ++j) { codedcards[i-1][j-1] = codedcards[i-1][j-1].modPow(d,mod).multiply(rprim[i-1]).mod(mod).modPow(e, mod);//multiply(rprimd).mod(mod); String cleancard = codedcards[i-1][j-1].toString(); //check if votes have correct length if(cleancard.length()!=10){ System.out.println("WRONG! CARD LENGTH!"); return false; } //card pattern to check if every vote on votingcard has the same number if (j==1) cardpattern = cleancard.substring(1); String cardnumber = cleancard.substring(1); if(cardnumber.compareTo(cardpattern)!=0){ System.out.println("WRONG! NOT EQUAL NUMBERS!"); return false; } //check if on cards have correct candidates String cand = Character.toString(cleancard.charAt(0)); //candidate number if(Integer.toString(j).compareTo(cand)!=0){ System.out.println("WRONG BAD CANDIDATE NUMBER!"); return false; } } } } return true; } /** * Sign card using blind vote */ public BigInteger[] signCard(){ if(norequest != null){ BigInteger[] signedCard = new BigInteger[candidates]; for (int j = 1; j <= candidates; ++j) signedCard[j-1] = codedcards[norequest][j-1].modPow(d,mod); return signedCard; } return null; } /** * check if vote after encrypt is formated correctly (if it is it means that vote * was decrypted by private key of VotingServer) */ public boolean checkVote(BigInteger vote){ vote = vote.modPow(e,mod); int candidate = Integer.parseInt(Character.toString(vote.toString().charAt(0))); //check here if vote is unique (in database) if(vote.toString().length()==10 && candidate <= candidates && candidate >= 0){ collectVote(vote); return true; } System.out.println("VOTE INCORRECT!:"+vote.toString()); return false; } /** * add vote to database */ private void collectVote(BigInteger vote){ //add here function to add vote to database System.out.println("VOTE:"+vote+" ADDED TO DATABASE."); } } |
And finally example of local usage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package blindsignature; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchProviderException; import java.security.SecureRandom; import java.security.SignatureException; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; /** * Blind Signature is a class which presents how to use VotingClient and * VotingServer Class to do full process of voting with blind signature * * * @author Pawel Maniora * @version 0.2, 20/01/12 */ public class BlindSignature { /** * number of candidates on voting cards */ final static int CANDIDATES = 4; /** * numbers of cards - the higher amount - the safer and * slower voting is. */ final static int CARDAMOUNT = 4; /** * server-side of blind signature voting module. */ public static VotingServer vs; /** * client-side of blind signature voting module. */ public static VotingClient vc; /** * @param args the command line arguments */ public static void main(String[] args) throws NoSuchProviderException, InvalidKeyException, SignatureException { try { //Create VotingServer and VotingClient //VotingServer should be created for each voter - it keeps codedCards, // randomly choosen number etc. vs = new VotingServer(CANDIDATES,CARDAMOUNT,d,e,mod); vc = new VotingClient(CANDIDATES,CARDAMOUNT,e,mod); //send coded cards from client to server vs.setCodedCards(vc.getCodedCards()); //VotingServer draw no request parameter and send info to VotingClient vc.setRfinal(vs.drawNoRequest()); //VotingServer gets info about r' parameters and if its okay sand signed card to client if(vs.checkCards(vc.getRprim())) vc.setSignedCard(vs.signCard()); //after Reconnect in anonymous connection // send vote on candidate (2 is third in this example) to serwer. if everything is okay vote is added. vc.isVoteAccepted(vs.checkVote(vc.sendVote(2))); }catch (java.security.NoSuchAlgorithmException e) {System.out.println("NoSuchAlgorithmException");} } } |
You can download sources from here
