基于变色龙哈希的可修改区块链
import hashlib import string import json import random import threading from decimal import Decimal from time import time import newChameleonHash length=50 n=0 p,q,g=newChameleonHash.Setup(length) SKlist,PKlist,rlist=[],[],[] class MyThread(threading.Thread): def __init__(self, target, args=()): super(MyThread, self).__init__() self.func = target self.args = args def run(self): self.result = self.func(*self.args) def get_result(self): try: return self.result except Exception: return None class BlockChain: def __init__(self, initialHash): # init block chain self.chain = [] # init pitman self.pitmen = [] for i in range(6): self.pitmen.append(Pitman) # collect mine results self.results = [] # generate GenesisBlock self.new_block(initialHash) @property def last_block(self): if len(self.chain): return self.chain[-1] else: return None def get_trans(self): return json.dumps({ 'sender': ''.join(random.sample(string.ascii_letters + string.digits, 8)), 'recipient': ''.join(random.sample(string.ascii_letters + string.digits, 8)), 'amount': random.randint(1, 10000) }) def new_block(self, initialHash=None): global n if initialHash: # generate Genesis Block block = Block() block.index = 0 block.SK=newChameleonHash.getSecretKey(q) block.PK=newChameleonHash.getPublicKey(g,block.SK,p) block.nonce = newChameleonHash.getr(q) block.previousHash = '0' block.difficulty = 0 block.transactionData = self.get_trans() SKlist.append(block.SK) PKlist.append(block.PK) rlist.append(block.nonce) n+=1 guess = f'{block.previousHash}{block.transactionData}' block.hash = str(hex(newChameleonHash.ChameleonHash(PKlist,guess,rlist,p,q,g,n))).replace('0x','') block.time = time() self.chain.append(block) else: for i in range(len(self.pitmen)): pm = MyThread(target=self.pitmen[i].mine, args=(self.pitmen[i], len(self.chain), self.last_block.get_block()['Hash'], self.get_trans())) pm.start() pm.join() self.results.append(pm.get_result()) # show all blocks #print("All blocks generated by pitmen:") #for result in self.results: # print(result[0].get_block()) # get new block firstblock = self.results[0][0] mintime = Decimal(self.results[0][1]) for i in range(1, len(self.results)): if Decimal(self.results[i][1]) < mintime: firstblock = self.results[i][0] else: continue self.chain.append(firstblock) SKlist.append(firstblock.SK) PKlist.append(firstblock.PK) rlist.append(firstblock.nonce) n+=1 self.results = [] def show_chain(self): print('This is mine first block chain!') for block in self.chain: print(block.get_block()) print('') def changeMSG(self,i,newtransactionData): block=self.chain[i-1] guess = f'{block.previousHash}{block.transactionData}' hash = str(hex(newChameleonHash.ChameleonHash(PKlist,guess,rlist,p,q,g,i))).replace('0x','') #print(hash) newguess = f'{block.previousHash}{newtransactionData}' newnonce=newChameleonHash.Forge(SKlist,guess,rlist,newguess,p,q,g,n,i) #print(newnonce) rlist[i-1]=newnonce newhash = str(hex(newChameleonHash.ChameleonHash(PKlist,newguess,rlist,p,q,g,i))).replace('0x','') #print(newhash) block.guess=guess block.transactionData=newtransactionData print(hash) print(newhash) class Block: def __init__(self): self.index = None self.time = None self.difficulty = None self.SK = None self.PK = None self.nonce = None self.hash = None self.previousHash = None self.transactionData = None def get_block(self): return { 'Index': self.index, 'Time': self.time, 'Difficulty': self.difficulty, 'Hash': self.hash, 'SK': self.SK, 'PK':self.PK, 'Nonce': self.nonce, 'PreviousHash': self.previousHash, 'TransactionData': self.transactionData } class Pitman: def mine(self, index, previousHash, transactionData): beginTime = time() block = Block() block.index = index block.previousHash = previousHash block.transactionData = transactionData block.difficulty, block.hash,block.SK,block.PK, block.nonce = self.generate_hash(previousHash, transactionData) block.time = time() endTime = time() return block, endTime - beginTime @staticmethod def generate_hash(previousHash, transactionData): difficulty = 0 SK=newChameleonHash.getSecretKey(q) PK=newChameleonHash.getPublicKey(g,SK,p) nonce = newChameleonHash.getr(q) SKlist.append(SK) PKlist.append(PK) rlist.append(nonce) a=n a+=1 guess = f'{previousHash}{transactionData}' myhash = str(hex(newChameleonHash.ChameleonHash(PKlist,guess,rlist,p,q,g,a))).replace('0x','') while myhash[-1] != '0': difficulty += 1 nonce += difficulty guess = f'{previousHash}{transactionData}' del rlist[-1] rlist.append(nonce) myhash = str(hex(newChameleonHash.ChameleonHash(PKlist,guess,rlist,p,q,g,a))).replace('0x','') del SKlist[-1] del PKlist[-1] del rlist[-1] return difficulty, myhash, SK,PK,nonce def vote(i): num=0 agreelist=[] for j in range(n): if j!=i-1: rand=random.randint(0,1) if rand==1: print('Index:',j,'同意修改') agreelist.append(j) num+=1 else: print('Index:',j,'拒绝修改') if num>int(n/2): print('修改请求通过') r=0 for k in range(num): random1=random.randint(1,q) print('Index:',agreelist[k],random1) r+=random1 temp=newChameleonHash.quickPower(g,r,p) chosen=agreelist[temp%num-1] print('Index:',chosen,'进行修改') return chosen else: print('修改请求被拒绝') return -1 if __name__ == '__main__': chain = BlockChain(1) length1 = 5 for i in range(length1): chain.new_block() chain.show_chain() while True: chosen=vote(3) if chosen!=-1: break newtransactionData='{"sender":"111","recipient":"222","amount":100}' chain.changeMSG(chosen,newtransactionData) chain.show_chain()
变色龙哈希
# n个用户,n个PK,SK,r,CH=g^m*h1^r1*h2^r2……hn^rn mod p #Setup(),KeyGen(),ChameleonHash(),Forge()四个函数 import random from pyunit_prime import get_large_prime_length #随机生成指定长度大素数 from pyunit_prime import is_prime #判断素数 from pyunit_prime import prime_range #输出指定区间素数 import math #p=0 #q=0 def primeFactorization(length): #分解质因数 #global p,q p,q=0,0 q=get_large_prime_length(length) while True: d=random.randint(2,10000) if d%2==0: p=q*d+1 if is_prime(p)==True: break else: continue else: continue primeList=prime_range(2,int(math.sqrt(d))) result=[[0,0] for i in range(len(primeList))] for i in range(len(primeList)): result[i][0]=primeList[i] while d%primeList[i]==0: result[i][1]+=1 d=d//primeList[i] if d!=1: result.append([d,1]) result.append([q,1]) return result,p,q def quickPower(a,b,c): #快速幂,a^b mod c result=1 while b>0: if b%2==1: result=result*a%c a=a*a%c b>>=1 return result def getGenerator(result,p,q): #get g generator=random.randint(1,1000) while True: if quickPower(generator,q,p)!=1: generator+=1 else: for i in range(len(result)): if quickPower(generator,int((p-1)/result[i][0]),p)==1: break if i!=len(result)-1: generator+=1 else: break return generator def Setup(length): factorization,p,q=primeFactorization(length) g=getGenerator(factorization,p,q) return p,q,g def getSecretKey(q): #get SKlist,x1,x2……xn SK=random.randint(1,q) return SK def getPublicKey(g,SK,p): #get PKlist,h1,h2……hn PK=quickPower(g,SK,p) return PK def getr(q): # rlist,r1,r2……rn r=random.randint(1,q) return r def treatMSG(msg): #处理消息msg为整数 newmsg='' for i in msg: newmsg+=str(ord(i)) return int(newmsg) def ChameleonHash(PKlist,m,rlist,p,q,g,n): #变色龙哈希 newm=treatMSG(m) CH=quickPower(g,newm,p) for i in range(n): CH=CH*quickPower(PKlist[i],rlist[i],p) CH=CH%p return CH def exgcd(a,b): #扩展欧几里得 if b==0: return 1,0,a else: x,y,gcd=exgcd(b,a%b) x,y=y,(x-(a//b)*y) return x,y,gcd def Forge(SKlist,m1,rlist,m2,p,q,g,n,i): #求r',线性同余方程 newm1=treatMSG(m1) newm2=treatMSG(m2) x,y,gcd=exgcd(SKlist[i-1],q) result=x*(newm1-newm2+SKlist[i-1]*rlist[i-1])%q return result