def test_encrypt_bad_version(self): with self.assertRaises(ECEException) as ex: ece.encrypt( self.m_input, version='bogus', key=self.m_key, ) self.assertEqual(ex.exception.message, "Invalid version")
def encode(self, data, content_encoding="aes128gcm"): """Encrypt the data. :param data: A serialized block of byte data (String, JSON, bit array, etc.) Make sure that whatever you send, your client knows how to understand it. :type data: str :param content_encoding: The content_encoding type to use to encrypt the data. Defaults to RFC8188 "aes128gcm". The previous draft-01 is "aesgcm", however this format is now deprecated. :type content_encoding: enum("aesgcm", "aes128gcm") """ # Salt is a random 16 byte array. if not data: return if not self.auth_key or not self.receiver_key: raise WebPushException("No keys specified in subscription info") salt = None if content_encoding not in self.valid_encodings: raise WebPushException("Invalid content encoding specified. " "Select from " + json.dumps(self.valid_encodings)) if content_encoding == "aesgcm": salt = os.urandom(16) # The server key is an ephemeral ECDH key used only for this # transaction server_key = ec.generate_private_key(ec.SECP256R1, default_backend()) crypto_key = server_key.public_key().public_bytes( encoding=serialization.Encoding.X962, format=serialization.PublicFormat.UncompressedPoint) if isinstance(data, six.string_types): data = bytes(data.encode('utf8')) if content_encoding == "aes128gcm": encrypted = http_ece.encrypt(data, salt=salt, private_key=server_key, dh=self.receiver_key, auth_secret=self.auth_key, version=content_encoding) reply = CaseInsensitiveDict({'body': encrypted}) else: crypto_key = base64.urlsafe_b64encode(crypto_key).strip(b'=') encrypted = http_ece.encrypt(data, salt=salt, private_key=server_key, keyid=crypto_key.decode(), dh=self.receiver_key, auth_secret=self.auth_key, version=content_encoding) reply = CaseInsensitiveDict({ 'crypto_key': crypto_key, 'body': encrypted, }) if salt: reply['salt'] = base64.urlsafe_b64encode(salt).strip(b'=') return reply
def test_encrypt_long_keyid(self): with self.assertRaises(ECEException) as ex: ece.encrypt( self.m_input, version='aes128gcm', key=self.m_key, keyid=b64e(os.urandom(192)), # 256 bytes ) self.assertEqual(ex.exception.message, "keyid is too long")
def test_encrypt_small_rs(self): with self.assertRaises(ECEException) as ex: ece.encrypt( self.m_input, version='aes128gcm', key=self.m_key, rs=1, ) self.assertEqual(ex.exception.message, "Record size too small")
def encryptDecrypt(length, encryptParams, decryptParams=None): if decryptParams is None: decryptParams = encryptParams if "key" in encryptParams: logbuf("Key", encryptParams["key"]); logbuf("Salt", encryptParams["salt"]) if "authSecret" in encryptParams: logbuf("Context", encryptParams["authSecret"]) input = os.urandom(min(length, maxLen)) # input = new Buffer("I am the walrus") logbuf("Input", input) encrypted = ece.encrypt(input, salt=encryptParams.get("salt"), key=encryptParams.get("key"), keyid=encryptParams.get("keyid"), dh=encryptParams.get("dh"), rs=encryptParams.get("rs"), authSecret=encryptParams.get("authSecret")) logbuf("Encrypted", encrypted) decrypted = ece.decrypt(encrypted, salt=decryptParams.get("salt"), key=decryptParams.get("key"), keyid=decryptParams.get("keyid"), dh=decryptParams.get("dh"), rs=decryptParams.get("rs"), authSecret=decryptParams.get("authSecret")) logbuf("Decrypted", decrypted) assert input == decrypted log("----- OK");
def encode(self, data): """Encrypt the data. :param data: A serialized block of data (String, JSON, bit array, etc.) Make sure that whatever you send, your client knows how to understand it. """ # Salt is a random 16 byte array. salt = os.urandom(16) # The server key is an ephemeral ECDH key used only for this # transaction server_key = pyelliptic.ECC(curve="prime256v1") # the ID is the base64 of the raw key, minus the leading "\x04" # ID tag. server_key_id = base64.urlsafe_b64encode(server_key.get_pubkey()[1:]) # http_ece requires that these both be set BEFORE encrypt or # decrypt is called if you specify the key as "dh". http_ece.keys[server_key_id] = server_key http_ece.labels[server_key_id] = "P-256" encrypted = http_ece.encrypt( bytes_compat(data), salt=salt, keyid=server_key_id, dh=self.receiver_key, authSecret=self.auth_key) return CaseInsensitiveDict({ 'crypto_key': base64.urlsafe_b64encode( server_key.get_pubkey()).strip(bytes_compat('=')), 'salt': base64.urlsafe_b64encode(salt).strip(bytes_compat("=")), 'body': encrypted, })
def main(): if len(sys.argv) < 4: #print ("usage: python push-encryption.py <client-pub-key> <server-auth> <message>") sys.exit(1) # generate ephemerial public key using ecdh serverECDH = pyelliptic.ECC(curve="prime256v1") serverPubKey = b64e(serverECDH.get_pubkey()[1:]) http_ece.keys[serverPubKey] = serverECDH http_ece.labels[serverPubKey] = "P-256" salt = os.urandom(16) clientPubKey64 = sys.argv[1] clientPubKey = base64.urlsafe_b64decode(clientPubKey64) clientAuthSecret64 = sys.argv[2] clientAuthSecret = base64.urlsafe_b64decode(clientAuthSecret64) messageRaw = sys.argv[3] messageRaw = messageRaw.encode('utf8') messageRaw = buffer(messageRaw) messageEncrypted = http_ece.encrypt(messageRaw, salt=salt, keyid=serverPubKey, dh=clientPubKey, authSecret=clientAuthSecret) print ("%s,%s,%s" % (base64.urlsafe_b64encode(salt), base64.urlsafe_b64encode(serverECDH.get_pubkey()), base64.b64encode(messageEncrypted)), end="")
def main(): if len(sys.argv) < 4: #print ("usage: python push-encryption.py <client-pub-key> <server-auth> <message>") sys.exit(1) # generate ephemerial public key using ecdh serverECDH = pyelliptic.ECC(curve="prime256v1") serverPubKey = b64e(serverECDH.get_pubkey()[1:]) http_ece.keys[serverPubKey] = serverECDH http_ece.labels[serverPubKey] = "P-256" salt = os.urandom(16) clientPubKey64 = sys.argv[1] clientPubKey = base64.urlsafe_b64decode(clientPubKey64) clientAuthSecret64 = sys.argv[2] clientAuthSecret = base64.urlsafe_b64decode(clientAuthSecret64) messageRaw = sys.argv[3] messageRaw = messageRaw.encode('utf8') messageRaw = buffer(messageRaw) messageEncrypted = http_ece.encrypt(messageRaw, salt=salt, keyid=serverPubKey, dh=clientPubKey, authSecret=clientAuthSecret) print("%s,%s,%s" % (base64.urlsafe_b64encode(salt), base64.urlsafe_b64encode(serverECDH.get_pubkey()), base64.b64encode(messageEncrypted)), end="")
def encode(self, data, content_encoding="aesgcm"): """Encrypt the data. :param data: A serialized block of byte data (String, JSON, bit array, etc.) Make sure that whatever you send, your client knows how to understand it. :type data: str :param content_encoding: The content_encoding type to use to encrypt the data. Defaults to draft-01 "aesgcm". Latest draft-04 is "aes128gcm", however not all clients may be able to use this format. :type content_encoding: enum("aesgcm", "aes128gcm") """ # Salt is a random 16 byte array. if not data: return if not self.auth_key or not self.receiver_key: raise WebPushException("No keys specified in subscription info") salt = None if content_encoding not in self.valid_encodings: raise WebPushException("Invalid content encoding specified. " "Select from " + json.dumps(self.valid_encodings)) if (content_encoding == "aesgcm"): salt = os.urandom(16) # The server key is an ephemeral ECDH key used only for this # transaction server_key = ec.generate_private_key(ec.SECP256R1, default_backend()) crypto_key = base64.urlsafe_b64encode( server_key.public_key().public_numbers().encode_point() ).strip(b'=') if isinstance(data, six.string_types): data = bytes(data.encode('utf8')) encrypted = http_ece.encrypt( data, salt=salt, keyid=crypto_key.decode(), private_key=server_key, dh=self.receiver_key, auth_secret=self.auth_key, version=content_encoding) reply = CaseInsensitiveDict({ 'crypto_key': crypto_key, 'body': encrypted, }) if salt: reply['salt'] = base64.urlsafe_b64encode(salt).strip(b'=') return reply
def encrypt_decrypt(self, input, encrypt_params, decrypt_params=None, version=None): """Run and encrypt/decrypt cycle on some test data :param input: data for input :type length: bytearray :param encrypt_params: Dictionary of encryption parameters :type encrypt_params: dict :param decrypt_params: Optional dictionary of decryption parameters :type decrypt_params: dict :param version: Content-Type of the body, formulating encryption :type enumerate("aes128gcm", "aesgcm", "aesgcm128"): """ if decrypt_params is None: decrypt_params = encrypt_params logbuf("Input", input) if "key" in encrypt_params: logbuf("Key", encrypt_params["key"]) if version != "aes128gcm": salt = os.urandom(16) decrypt_rs_default = 4096 else: salt = None decrypt_rs_default = None logbuf("Salt", salt) if "auth_secret" in encrypt_params: logbuf("Auth Secret", encrypt_params["auth_secret"]) encrypted = ece.encrypt(input, salt=salt, key=encrypt_params.get("key"), keyid=encrypt_params.get("keyid"), dh=encrypt_params.get("dh"), private_key=encrypt_params.get("private_key"), auth_secret=encrypt_params.get("auth_secret"), rs=encrypt_params.get("rs", 4096), version=version) logbuf("Encrypted", encrypted) decrypted = ece.decrypt(encrypted, salt=salt, key=decrypt_params.get("key"), keyid=decrypt_params.get("keyid"), dh=decrypt_params.get("dh"), private_key=decrypt_params.get("private_key"), auth_secret=decrypt_params.get("auth_secret"), rs=decrypt_params.get("rs", decrypt_rs_default), version=version) logbuf("Decrypted", decrypted) self.assertEqual(input, decrypted)
def detectTruncation(): length = min(rlen(), maxLen) key = os.urandom(16) salt = os.urandom(16) rs = length + 2 input = os.urandom(min(length, maxLen)) encrypted = ece.encrypt(input, salt=salt, key=key, rs=rs) ok = False try: ece.decrypt(encrypted[0:length + 2 + 16], salt=salt, key=key, rs=rs) except Exception as e: log("Decryption error: %s" % e.args) log("----- OK") ok = True if not ok: raise Exception("Decryption succeeded, but should not have")
def detect_truncation(self, version): if version == "aes128gcm": return input = self._generate_input(2) key = os.urandom(16) salt = os.urandom(16) rs = len(input) + self._rsoverhead(version) - 1 encrypted = ece.encrypt(input, salt=salt, key=key, rs=rs, version=version) if version == 'aes128gcm': chunk = encrypted[0:21 + rs] else: chunk = encrypted[0:rs + 16] with self.assertRaises(ECEException) as ex: ece.decrypt(chunk, salt=salt, key=key, rs=rs, version=version) self.assertEqual(ex.exception.message, "Message truncated")
def encryptDecrypt(length, encryptParams, decryptParams=None): if decryptParams is None: decryptParams = encryptParams log('Salt: ' + b64e(encryptParams['salt'])) input = os.urandom(min(length, maxLen)) # input = new Buffer('I am the walrus') log('Input: ' + b64e(input)) encrypted = ece.encrypt(input, salt=encryptParams.get('salt'), key=encryptParams.get('key'), keyid=encryptParams.get('keyid'), dh=encryptParams.get('dh'), rs=encryptParams.get('rs')) log('Encrypted: ' + b64e(encrypted)) decrypted = ece.decrypt(encrypted, salt=decryptParams.get('salt'), key=decryptParams.get('key'), keyid=decryptParams.get('keyid'), dh=decryptParams.get('dh'), rs=decryptParams.get('rs')) log('Decrypted: ' + b64e(decrypted)) assert input == decrypted log("----- OK");
def encode(self, data): """Encrypt the data. :param data: A serialized block of byte data (String, JSON, bit array, etc.) Make sure that whatever you send, your client knows how to understand it. """ # Salt is a random 16 byte array. salt = os.urandom(16) # The server key is an ephemeral ECDH key used only for this # transaction server_key = pyelliptic.ECC(curve="prime256v1") # the ID is the base64 of the raw key, minus the leading "\x04" # ID tag. server_key_id = base64.urlsafe_b64encode(server_key.get_pubkey()[1:]) if isinstance(data, six.string_types): data = bytes(data.encode('utf8')) # http_ece requires that these both be set BEFORE encrypt or # decrypt is called if you specify the key as "dh". http_ece.keys[server_key_id] = server_key http_ece.labels[server_key_id] = "P-256" encrypted = http_ece.encrypt(data, salt=salt, keyid=server_key_id, dh=self.receiver_key, authSecret=self.auth_key) return CaseInsensitiveDict({ 'crypto_key': base64.urlsafe_b64encode(server_key.get_pubkey()).strip(b'='), 'salt': base64.urlsafe_b64encode(salt).strip(b'='), 'body': encrypted, })
def __encrypt__(self, user_publickey, user_auth, payload): """Encrypt the given payload.""" user_publickey = user_publickey.encode("utf8") raw_user_publickey = base64.urlsafe_b64decode( self.__b64rpad__(user_publickey) ) user_auth = user_auth.encode("utf8") raw_user_auth = base64.urlsafe_b64decode(self.__b64rpad__(user_auth)) salt = os.urandom(16) curve = pyelliptic.ECC(curve="prime256v1") curve_id = base64.urlsafe_b64encode(curve.get_pubkey()[1:]) http_ece.keys[curve_id] = curve http_ece.labels[curve_id] = "P-256" encrypted = http_ece.encrypt( payload.encode('utf8'), keyid=curve_id, dh=raw_user_publickey, salt=salt, authSecret=raw_user_auth, version="aesgcm" ) return { 'dh': base64.urlsafe_b64encode( curve.get_pubkey() ).strip(b'=').decode("utf-8"), 'salt': base64.urlsafe_b64encode( salt ).strip(b'=').decode("utf-8"), 'body': encrypted }