Exemplo n.º 1
0
  def renewCookie(self):
    # ensure the renewed cookie will be valid ie current cookie can actually decrypt the session vault
    if not CryW(cryptedObj=self.userDict['saes'], bytesPwrd=En(En(self.cookieIn)._by64()[16:])._sha256()).decrypt():
      return False

    # create a new session vault with known, same private Ed25519 key but change the 'secret' and time hence AES key too
    cookieBytes = self.ioUUID(self.userDict['uuid']) + En()._rnd(32) + af.itb(int(time.time()))
    self.cookieOut = En(cookieBytes)._b64()
    self.sql.replaceRows('users', {
      **self.userDict,
      'saes': CryW(bytesMessage = self.priv, bytesPwrd = En(cookieBytes[16:])._sha256()).encrypt(),
    })

    return True
Exemplo n.º 2
0
  def parseCookie(self):
    # b64 → bytes, huuid (16 bytes) + AES 'secret' + time (UTC/*nix)
    cookieBytes = En(self.cookieIn)._by64()
    huuid, phKey, ts = cookieBytes[0:16], cookieBytes[16:48], cookieBytes[48:]

    # from bytes huuid get uuid len 36 which IDs user and get SQL dict (line) for this user
    self.userDict = self.sql.getOneDataDict('users', 'uuid', self.ioUUID(huuid))

    # in case login from cookie
    if not self.email:
      if False if not self.userDict else self.userDict.get('email'):
        self.email = self.userDict.get('email')
      else:
        return False

    # check that cookie not expired
    if int(time.time()) - gv.COOKIE.MAX > af.ifb(cookieBytes[48:]):
      return False

    if not self.userDict:
      return False

    # concatenate AES 'secret' with time and SHA256 hash to get AES key to decrypt 'saes' session vault and get
    # Ed25519 private key
    self.priv = CryW(cryptedObj = self.userDict['saes'], bytesPwrd = En(phKey + ts)._sha256()).decrypt()

    # keyring
    if self.priv:
      self.keyring = Crypt25519(self.priv, self.userDict['pub'])

    return bool(self.priv)
Exemplo n.º 3
0
  def getChallenge(self):
    if not self.userDict:
      return False

    # none if never logged in + case where first login ever *or* reset email password
    privateKeys = {
      'current': self.userDict['priv'],
      'next': self.parseNextKeys(self.userDict['nextkeys'])[3]
    }


    self.response['challenge'] = {k: En(CryW.getChallenge(v))._b64() for k, v in privateKeys.items() if v}

    return self
Exemplo n.º 4
0
  def changePassword(self, newHash, pub, priv):
    testBytes = En()._rnd(32)
    assert( testBytes == Crypt25519(privateBytes=priv).decrypt(Crypt25519(publicBytes=pub).encrypt(testBytes)) )

    self.userDict.update({
      'nextkeys': None,
      'priv': CryW(bytesMessage = newHash + priv, bytesPwrd = newHash).encrypt(),
      'pub': pub,
      'pwrdchange': 0
    })

    self.sql.replaceRows('users', self.userDict)
    self.sql.reconnect()

    self.response['type'] = 'passwordchanged'
Exemplo n.º 5
0
asymKC = Crypt25519()

t = time.time()
for plain in plains:
    asym = asymKC.encrypt(plain)
    dasym = Crypt25519(asymKC.privateBytes, asymKC.publicBytes).decrypt(asym)
    assert (dasym == plain)

print(time.time() - t)

aes = En().rnd(16)._sha256()

t = time.time()
for plain in plains:
    sym = CryW(bytesMessage=plain, bytesPwrd=aes, slow=1).encrypt()
    dsym = CryW(cryptedObj=sym, bytesPwrd=aes, slow=1).decrypt()

    assert (dsym == plain)

print(time.time() - t)


# speed test
def makeNotes(n=1, z=1):
    generator = getattr(lipsum, {
        0: 'generate_words',
        1: 'generate_sentences'
    }.get(random.randint(0, 1)))

    return {
Exemplo n.º 6
0
def bj(obj, aes = None):
  compressed = CryW(cryptedObj = obj, bytesPwrd = aes).decrypt() if aes else obj
  if not compressed:
    return False
  return json.loads(zlib.decompress(compressed))
Exemplo n.º 7
0
def jb(obj, aes = None):
  compressed = zlib.compress(En(json.dumps(obj))._by())
  return CryW(bytesMessage = compressed, bytesPwrd = aes).encrypt() if aes else compressed
Exemplo n.º 8
0
 def newKeypair(self):
   password = En()._rnd58(8)
   keys25519 = Crypt25519()
   return password, CryW(bytesMessage=En(password)._sha512u() + keys25519.privateBytes,
                         bytesPwrd=En(password)._sha512u()).encrypt(), keys25519.publicBytes
Exemplo n.º 9
0
  def getCookie(self, login):
    self.response['cookie'] = ''
    self.getChallenge()
    # get encrypted vault for this user and try to decrypt
    decrypted = {
      k: CryW(
        cryptedObj = self.userDict['priv'] if k == 'current' else self.parseNextKeys(self.userDict['nextkeys'])[3],
        pbkd = En(v)._by64()
      ).decrypt() for k, v in login.pbkdf2b64.items()
    }

    decrypted = {k: v for k, v in decrypted.items() if v}


    # analyze content of dict to figure out what type is to be sent to front end -> standard, reset, change, first
    # (cookie and forgot are other 'types' but not relevant here)
    if self.userDict['nextkeys']:
      type = 'reset' if self.userDict['priv'] else 'first'
      if not decrypted:
        self.response['type'] = type
        return self
      if not login.newhash and (not decrypted.get('current') or type == 'first'):
        self.response['type'] = type
        return self
    else:
      type = 'change' if self.userDict['pwrdchange'] else 'standard'
      if not decrypted:
        self.response['type'] = type
        return self
      if not login.newhash and type == 'change':
        self.response['type'] = 'change'
        return self

    self.response['type'] = 'standard'

    # we can cancel the request as user knows password
    if type == 'reset':
      if decrypted.get('current'):
        self.sql.wesc(f"UPDATE users SET nextkeys* WHERE uuid*", v = [(None, self.userDict['uuid'])])
        self.userDict['nextkeys'] = None
      else:
        if not login.newhash:
          self.response['type'] = 'reset'
          return self

    # case where 'nextkeys' needs to be moved to usual permanents vaults ie new user or pwrd reset (not change, reset)
    if set(decrypted.keys()) == {'next'}:
      _, _, pub, _ = self.parseNextKeys(self.userDict['nextkeys'])
      self.hashedpwrd, self.priv = af.En(login.newhash)._by64(), decrypted.get('next')[64:]
      self.changePassword(self.hashedpwrd, pub, self.priv)

      # enable lists where assigned
      if type == 'first':
        self.sql.wesc(f"UPDATE rights SET disp* WHERE uuid*", v = [(1, self.userDict['uuid'])])
      else:
      # otherwise if reset then all keys are lost :(
        self.sql.wesc(f"UPDATE rights SET aes* WHERE uuid*", v = [(None, self.userDict['uuid'])])

    else:
      # decrypt the user's vault which contains (1) the hashed pwrd and (2) the private Ed25519 key
      self.hashedpwrd, self.priv = decrypted.get('current')[0:64], decrypted.get('current')[64:]

    # case where we are just Δing password
    if type == 'change':

      self.hashedpwrd = af.En(login.newhash)._by64()
      self.changePassword(self.hashedpwrd, self.userDict['pub'], self.priv)


    # cookie content in bytes: 16 bytes for uuid, 32 bytes of session AES 'secret' (not key) and time UTC, make b64 cookie
    cookieBytes = self.ioUUID(self.userDict['uuid']) + En()._rnd(32) + af.itb(int(time.time()))
    self.cookieOut = En(cookieBytes)._b64()

    # then rotate user's vault (avoid replay attack if XSS attack getting client-generated PBKDF2) and generate session
    # AES vault which is a SHA256 hashed combination of AES 'secret' above with time UTC so even a corrupt browser
    # can't fake cookie time generation to server as the hash which decrypts the session vault would change
    self.sql.replaceRows('users', {
      **self.userDict,
      'priv': CryW(bytesMessage = self.hashedpwrd + self.priv, bytesPwrd = self.hashedpwrd).encrypt(),
      'saes': CryW(bytesMessage = self.priv, bytesPwrd = En(cookieBytes[16:])._sha256()).encrypt(),
    })

    self.keyring = Crypt25519(self.priv, self.userDict['pub'])

    self.response['cookie'] = self.cookieOut

    return self
Exemplo n.º 10
0
    self.response['challenge'] = {k: En(CryW.getChallenge(v))._b64() for k, v in privateKeys.items() if v}

    return self

  def parseNextKeys(self, nextKeys):
    if not nextKeys:
      return b'', b'', b'', b''
    return af.ifb(nextKeys[0:4]), nextKeys[4:36], nextKeys[36:68], nextKeys[68:]




password = '******'
msg= b'\x16C\xd8\xa6\xc1\xdb~\xcdY\xc3\xd77\xeb\xfe\xa1\x0e\x9c\xe4\xdc:m5\xe7\xf5|\xc1\xb2U\x15\xbb\xe9\xd6\x86\xc1\xd8\xdcM\xb2\xeez\xd3\xe5C\xb9o\x1eN\x040\x19_\xe6\xc8\x9b\xdee\x95\xe2t\xe9\x82\xdd\xf5\t\x80U\xeb/\x08\xab~\xe5\x86"\xdf\xf2\xf2\x04!P\xae\xc5\xe9tv\x1c\xb9|\xbd\x99\xd2\xf1V\x14\x04\xac'
cipher = CryW(bytesMessage = msg, bytesPwrd = En(password)._sha512u()).encrypt()

CryW(cryptedObj = cipher, bytesPwrd = En(password)._sha512u()).decrypt()