Example #1
0
 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")
Example #2
0
    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
Example #3
0
 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")
Example #4
0
 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");
Example #6
0
    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,
        })
Example #7
0
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="")
Example #8
0
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="")
Example #9
0
    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
Example #10
0
    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")
Example #12
0
    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");
Example #14
0
    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,
        })
Example #15
0
    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
        }