diff --git a/__pycache__/lazarus.cpython-38.pyc b/__pycache__/lazarus.cpython-38.pyc new file mode 100644 index 0000000..b796df8 Binary files /dev/null and b/__pycache__/lazarus.cpython-38.pyc differ diff --git a/__pycache__/main.cpython-36.pyc b/__pycache__/main.cpython-36.pyc deleted file mode 100644 index 44726a1..0000000 Binary files a/__pycache__/main.cpython-36.pyc and /dev/null differ diff --git a/bethany.py b/bethany.py new file mode 100644 index 0000000..f097641 --- /dev/null +++ b/bethany.py @@ -0,0 +1,87 @@ +from fastecdsa.curve import P256 +from fastecdsa.point import Point +from fastecdsa import util + +from lazarus import Lazarus + +class Bethany(): + pass + +#--- + +e = 31415926535987932384626433832795 +Q = e*P256.G + +class Generalised_Dual_EC_RBG(object): + def __init__(self, Q, seed, curve = P256): + self.curve = curve + self.state = seed + self.Q = Q + self.P = curve.G + self.tmp = None + + assert Q.curve == curve + + def gen(self): + new_point = self.state * self.P + sP = r = new_point.x # remember that the x value of the new point is used for the next point. + rQ = r * self.P + random_int_to_return = int(str(bin((rQ).x))[16:], 2) + self.state = (r*self.Q).x + self.lsb = str(bin((rQ).x)) + self.rQ = rQ + return random_int_to_return + +class breakEccPerm(): + def __init__(self): + pass + + def smash(omegaKey): + integer = int.from_bytes(omegaKey, "big", seed, signed=False ) + breakEccPerm.get_identical_generator(integer, second_output, e, curve) + + def get_identical_generator(output, second_output, e, curve): + # make a new generator and instantiate it with one possible state out of the 65535 + for lsb in range(2**16): + # rudimentary progress bar + if (lsb % 2048) == 0: + print("{}% done checking\r".format(100*lsb/(2**16))) + # bit-shift and then concat to guess most significant bits that were discarded + overall_output = (lsb << (output.bit_length()) | output) + + # zeroth check: is the value greater than p? + if overall_output > curve.p: + global first_rQ # this is only used for debugging and can be removed + # if it is greater, skip this number + # since the most significant bits are iterated through in ascending order. + # if it reaches that point that means we know something went wrong and we can break out + print("""Something went wrong. debugging info: + Output = {}, + lsb = {}, + rQ = {}""".format(output, lsb, first_rQ)) + break + + # calculate a value of y + for sol_to_y in util.mod_sqrt(overall_output**3 - 3*overall_output + curve.b, curve.p): + # there are either 2 or 0 real answers to the square root. We reject those greater than p. + if sol_to_y < curve.p: + possible_y = sol_to_y + else: + possible_y = None + # first check: if there were 0 solutions we can skip this iteration + if possible_y == None or type(possible_y) != int: + continue + + # second check: is point on curve? if not then skip this iteration + try: + possible_point = Point(overall_output, possible_y, curve=curve) + except: + continue + + # if checks were passed, exploit the relation between state to calculate the internal state + possible_state = (e * possible_point).x + # check if the state is correct by generating another output + possible_generator = Generalised_Dual_EC_RBG(Q=Q, seed=possible_state) + if possible_generator.gen() == second_output: + break + return possible_generator diff --git a/break.py b/break.py deleted file mode 100644 index 167d8f2..0000000 --- a/break.py +++ /dev/null @@ -1,180 +0,0 @@ -import os -import sys -import time -import random -import hashlib -import itertools -from base64 import b64encode as b64enc, b64decode as b64dec - -BS = 16 -iv = "0"*BS # set to "" if not known - -class bc: - HEADER = '\033[95m' - OKBLUE = '\033[94m' - OKGREEN = '\033[92m' - WARNING = '\033[93m' - FAIL = '\033[91m' - ENDC = '\033[0m' - BOLD = '\033[1m' - UNDERLINE = '\033[4m' - -def p(t): - sys.stdout.write(t) - - -s = "" -def printScreen(enc,dec,match,status="",less=False): - if less and random.random()maxLen: - break - for ni,n in enumerate(b): - if dec[bi][ni]=="0": - if match!=0: - matchInds = [] - for m in match[ni]: - for i in m[1]: - matchInds.append(i) - if bi in matchInds: - #p(bc.OKBLUE+b64enc(n)[0]+bc.ENDC) - p(b64enc(n)[0]) - else: - #p(b64enc(n)[0]) - p(bc.FAIL+"#"+bc.ENDC) - else: - p(bc.OKGREEN+dec[bi][ni]+bc.ENDC) - print("\n\n"+s+"\n\n") - #time.sleep(0.01) - -def cls(): - os.system('cls' if os.name=='nt' else 'clear') - -def sxor(s1,s2): - return ''.join(chr(ord(a) ^ ord(b)) for a,b in zip(s1,s2)) - -def main(enc): - c = [list(enc[i*BS:][:BS]) for i in range(int(ceil(float(len(enc))/BS)))] - enc = c - dec = [] - for i in enc: - dec.append(["0"]*BS) - printScreen(enc,dec,0,"Cross-Entropy-Mapping") - # nugget 1 nugget 2 - # [ [[char,block],...] , [...] , ... ] - seen = [] - # nugget 1 nugget 2 - # [ [[char,[index1,index2,...],...] , [...] , ... ] - match = [] - - # [[clash,indN,indA,indB],...] - tron = [] - for i in range(BS): - match.append([]) - seen.append([]) - for bi,b in enumerate(enc): #for every block - for ni,n in enumerate(b): #for every nugget - for mi,m in enumerate(match[ni]): - if m[0]==n: # Match already exists, add our new one - m[1].append(bi) # add our Block-Index to the Match - printScreen(enc,dec,match,"",2) - break - else: # No existing Match found; Searching for new one - for si,s in enumerate(seen[ni]): - if s[0]==n: #Found dat Match - # char,[bIndex Seen, bIndex New] - match[ni].append([n,[s[1],bi]]) - printScreen(enc,dec,match,"",2) - break - else: # No Match, Char not in seen - # char, bIndex - seen[ni].append([n,bi]) - - printScreen(enc,dec,match,"Calculating Trons...") - for ni,n in enumerate(match): #for every nugget - for mi,m in enumerate(n): #for every match - for indexA,indexB in itertools.combinations(m[1],2): #for every bIndex-Pair - if indexA==0: - if len(iv)!=0: - tron.append([ sxor(enc[indexB-1][ni],iv), ni, [indexA, indexB]]) - else: - tron.append([ sxor(enc[indexA-1][ni],enc[indexB-1][ni]), ni, [indexA, indexB]]) - - printScreen(enc,dec,match,"Constructing Matrix") - matrix = [] - for i in range(len(enc)*BS): - matrix.append([]) - for j in range(128): - matrix[i] = [1]*128 - - printScreen(enc,dec,match,"Planting Seeds...") - for ti,t in enumerate(tron): - bin = '{0:07b}'.format(ord(t[0])) - for b in [0,1]: - if bin[:2]=="00": - # is 00****** - # but to be valid, it has to be 001***** -> min 32 - for i in range(32): - matrix[t[2][b]*8+t[1]][i] = 0 - elif bin[:2]=="10": - # is 10****** - # first bit is not allowes to flip - for i in range(64,128): - matrix[t[2][b]*8+t[1]][i] = 0 - elif bin[:2]=="11": - # is 11****** - # first 2 bits are not allowes to flip - for i in range(96,128): - matrix[t[2][b]*8+t[1]][i] = 0 - elif bin[:2]=="01": - # is 01****** - # second bit is only allowed to flip, - # if first bit flips - for i in range(32,64): - matrix[t[2][b]*8+t[1]][i] = 0 - - legals = [] - legals.append([45,46,47]) - legals.append(range(65,90)) - legals.append([95]) - legals.append([97,122]) - - tronHistory = [] - - printScreen(enc,dec,match,"Growing Seeds...") - while True: - p(".") - hash = hashlib.sha256(str(tron)).hexdigest() - if hash in tronHistory: - break - tronHistory.append(hash) - for ti,t in enumerate(tron): - for direction in [0,1]: - for possibilityA,avaibleA in enumerate(matrix[t[2][direction]*8+t[1]]): - if avaibleA: - for possibilityB,avaibleB in enumerate(matrix[t[2][direction]*8+t[1]]): - if avaibleB: - if (possibilityA ^ possibilityB) not in legals: - matrix[t[2][direction]*8+t[1]][possibilityA] = 0 - matrix[t[2][direction]*8+t[1]][possibilityB] = 0 - for m in matrix: - l = 0 - for i in m: - if i: - l+=1 - if l==1: - print("Yay!") - -if __name__=="__main__": - from lazarus import * - lazarus = Lazarus("This is a safe Password") - knownDec = "This is a very very long text message, that I use to text my text. If you read this text, dont think it is your text just because you read it, it is still my text! So: Fuck of and get you own text, if you want one, asshole..."*200 - enc = lazarus.enc(knownDec) - main(enc) diff --git a/lazarus.py b/lazarus.py index 4755c18..e0f8bc3 100644 --- a/lazarus.py +++ b/lazarus.py @@ -1,48 +1,110 @@ -from math import ceil -from urllib2 import quote, unquote -from base64 import b64encode as b64enc +import hashlib +import math + +from fastecdsa.curve import P256 +from fastecdsa.point import Point +from fastecdsa import util + +Q = 31415926535987932384626433832795*P256.G + +class EccRNG(): + def __init__(self, Q, seed, curve = P256): + self.curve = curve + self.state = int.from_bytes(seed, "big", seed, signed=False ) + self.Q = Q + self.P = curve.G + self.tmp = None + assert Q.curve == curve + + def gen(self): + new_point = self.state * self.P + r = new_point.x + rQ = r * self.P + random_int_to_return = int(str(bin((rQ).x))[16:], 2) + self.state = (r*self.Q).x + self.lsb = str(bin((rQ).x)) + self.rQ = rQ + return random_int_to_return.to_bytes(math.ceil(random_int_to_return.bit_length()/8), byteorder='big') + +class LazarusKeyScheduler(): + def __init__(self, password: bytes, nonce: bytes): + self.ecc = EccRNG() + self.hashState = hashlib.sha3_256(password + nonce + password).digest() + self.eccState = self.ecc.gen() + for i in range(64): + self._stateStep() + + def genToken(self): + self._stateStep() + return self.state + self.eccState + + def getKey(self, length: int): + return hashlib.shake_256(self.genToken()).digest(length) + + def _stateStep(self): + self.eccState = self.ecc.gen() + self.hashState = hashlib.sha3_256(self.hashState + self.eccState).digest() + +class OmegaChain(): + def __init__(self, key: bytes, primer: bytes): + self.blockSize = 16 + self.prevBlock = primer + self.key = key + + def encrypt(self, data: bytes): + blocks = self._dataToBlocks(data) + enc = bytes() + for block in blocks: + enc += self.encBlock(block) + + def _encBlock(self, plainBlock: bytes): + chainedBlock = self._xor(self.prevBlock, plainBlock) + encBlock = self._xor(chainedBlock, self.key) + self.prevBlock = encBlock + return encBlock + + def _xor(self, a: bytes, b: bytes): + if len(a)!=self.blockSize or len(b)!=self.blockSize: + raise Exception("Cannot xor") #TODO + return bytes([a[i]^b[i] for i in range(len(a))]) + + def _dataToBlocks(self, data: bytes): + padded = self._padData(data, blockSize = self.blockSize) + return [data[b*self.blockSize:self.blockSize] for b in range(int(len(padded)/self.blockSize))] + + def _padData(self, data: bytes, blockSize: int = None): + if not blockSize: + blockSize = self.blockSize + bytesMissing = (blockSize-len(data)%blockSize) + if bytesMissing == blockSize: + return data + else: + return data + bytes(bytesMissing) class Lazarus(): - def __init__(self, key): - self.key = key - self.BS = 16 - self.iv = "0"*self.BS + def encrypt(password: bytes, plaintext: bytes, nonce: bytes = None): + if not nonce: + #TODO: Random iv + nonce = b'bla' + scheduler = LazarusKeyScheduler(password, nonce) + omegaKey = scheduler.genToken() + primer = scheduler.getKey(16) + aesKey = scheduler.getKey(16) + aesIV = scheduler.getKey(16) + hmacInnerKey = scheduler.getKey(16) + hmacOuterKey = scheduler.getKey(16) - def enc(self, plaintext): - t = quote(plaintext) - prevBlock = self.iv - c = "" - for i in range(int(ceil(float(len(t))/self.BS))): - block = t[i*self.BS:][:self.BS] - prevBlock=self._sxor(self._rc4(block),prevBlock) - c+=prevBlock - return c + alpha = Lazarus._encryptAES(plaintext, aesKey, aesIV) + hmac = Lazarus._genHMAC(plaintext, hmacInnerKey, hmacOuterKey) + psi = alpha + hmac + omega = OmegaChain(omegaKey, primer) + return omega.encrypt(psi) - def dec(self, ciphertext): - c = ciphertext - prevBlock = self.iv - t = "" - for i in range(int(ceil(float(len(c))/self.BS))): - block = c[i*self.BS:][:self.BS] - t+=self._rc4(self._sxor(block,prevBlock)) - prevBlock = block - return unquote(t) + def omegaChain(prev: bytes, scheduler: LazarusKeyScheduler): + pass - def _sxor(self, s1, s2): - return ''.join(chr(ord(a) ^ ord(b)) for a,b in zip(s1,s2)) + def eccPerm(self, key: bytes): + pass - def _rc4(self, data): - box = list(range(256)) - x = 0 - for i in range(256): - x = (x + box[i] + ord(self.key[i % len(self.key)])) % 256 - box[i], box[x] = box[x], box[i] - x = 0 - y = 0 - out = [] - for char in data: - x = (x + 1) % 256 - y = (y + box[x]) % 256 - box[x], box[y] = box[y], box[x] - out.append(chr(ord(char) ^ box[(box[x] + box[y]) % 256])) - return ''.join(out) + def primePerm(self, key: bytes): + pass diff --git a/lazarus.pyc b/lazarus.pyc deleted file mode 100644 index f5c6788..0000000 Binary files a/lazarus.pyc and /dev/null differ diff --git a/note.py b/note.py deleted file mode 100644 index ec16674..0000000 --- a/note.py +++ /dev/null @@ -1,48 +0,0 @@ - -class AESModeOfOperationCBC(AESBlockModeOfOperation): - '''AES Cipher-Block Chaining Mode of Operation. - o The Initialization Vector (IV) - o Block-cipher, so data must be padded to 16 byte boundaries - o An incorrect initialization vector will only cause the first - block to be corrupt; all other blocks will be intact - o A corrupt bit in the cipher text will cause a block to be - corrupted, and the next block to be inverted, but all other - blocks will be intact. - Security Notes: - o This method (and CTR) ARE recommended. - Also see: - o https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher-block_chaining_.28CBC.29 - o See NIST SP800-38A (http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf); section 6.2''' - - - name = "Cipher-Block Chaining (CBC)" - - def __init__(self, key, iv = None): - if iv is None: - self._last_cipherblock = [ 0 ] * 16 - elif len(iv) != 16: - raise ValueError('initialization vector must be 16 bytes') - else: - self._last_cipherblock = _string_to_bytes(iv) - - AESBlockModeOfOperation.__init__(self, key) - - def encrypt(self, plaintext): - if len(plaintext) != 16: - raise ValueError('plaintext block must be 16 bytes') - - plaintext = _string_to_bytes(plaintext) - precipherblock = [ (p ^ l) for (p, l) in zip(plaintext, self._last_cipherblock) ] - self._last_cipherblock = self._aes.encrypt(precipherblock) - - return _bytes_to_string(self._last_cipherblock) - - def decrypt(self, ciphertext): - if len(ciphertext) != 16: - raise ValueError('ciphertext block must be 16 bytes') - - cipherblock = _string_to_bytes(ciphertext) - plaintext = [ (p ^ l) for (p, l) in zip(self._aes.decrypt(cipherblock), self._last_cipherblock) ] - self._last_cipherblock = cipherblock - - return _bytes_to_string(plaintext)