Ejemplo n.º 1
0
 def generate_recovery_key(prv_key):
     rec_key = _GCE.generate_key()
     pub_key = PrivateKey(prv_key,
                          Base64Encoder).public_key.encode(Base64Encoder)
     bkp_key = _GCE.symmetric_encrypt(rec_key, prv_key)
     rec_key = _GCE.asymmetric_encrypt(pub_key, rec_key)
     return Base64Encoder.encode(bkp_key), Base64Encoder.encode(rec_key)
Ejemplo n.º 2
0
def validate_password_reset(session, reset_token, auth_code, recovery_key):
    """
    Retrieves a user given a password reset validation token

    :param session: An ORM session
    :param reset_token: A reset token
    :param auth_code: A two factor authentication code (optional)
    :param recovery_key: An encryption recovery key (optional)
    :return: A descriptor describing the result of the operation
    """
    now = datetime.now()
    prv_key = ''

    user = session.query(models.User).filter(
        models.User.reset_password_token == reset_token,
        models.User.reset_password_date >= now - timedelta(hours=72)
    ).one_or_none()

    # If the authentication token is invalid
    if user is None:
        return {'status': 'invalid_reset_token_provided'}

    # If encryption is enabled require the recovery key
    if user.crypto_prv_key:
        try:
            x = State.TempKeys.pop(user.id, None)
            if x:
                enc_key = GCE.derive_key(reset_token.encode(), user.salt)
                prv_key = GCE.symmetric_decrypt(enc_key, Base64Encoder.decode(x.key))
            else:
                recovery_key = recovery_key.replace('-', '').upper() + '===='
                recovery_key = Base32Encoder.decode(recovery_key.encode())
                prv_key = GCE.symmetric_decrypt(recovery_key, Base64Encoder.decode(user.crypto_bkp_key))
        except:
            return {'status': 'require_recovery_key'}

    elif user.two_factor_enable:
        two_factor_secret = user.two_factor_secret
        if not pyotp.TOTP(two_factor_secret).verify(auth_code, valid_window=1):
            return {'status': 'require_two_factor_authentication'}

    # Token is used, void it out
    user.reset_password_token = None
    user.reset_password_date = now

    # Require password change
    user.password_change_needed = True

    session = Sessions.new(user.tid, user.id,
                           user.tid, user.role,
                           user.password_change_needed,
                           user.two_factor_enable,
                           prv_key,
                           user.crypto_escrow_prv_key)

    return {'status': 'success', 'token': session.id}
Ejemplo n.º 3
0
    def handle(self, *args, **options):
        """Handle the command"""
        private_key = PrivateKey.generate()
        public_key = private_key.public_key

        self.stdout.write('--------------------------------------------------------------')
        self.stdout.write('Private Key Base64 Encoded:')
        self.stdout.write(Base64Encoder.encode(bytes(private_key)).decode("utf-8"))
        self.stdout.write('--------------------------------------------------------------')
        self.stdout.write('Public Key Base64 Encoded:')
        self.stdout.write(Base64Encoder.encode(bytes(public_key)).decode("utf-8"))
        self.stdout.write('--------------------------------------------------------------')
Ejemplo n.º 4
0
    def test_base64_smessage_with_detached_sig_matches_with_attached_sig(self):
        sk = SigningKey.generate()
        vk = sk.verify_key

        smsg = sk.sign(b"Hello World in base64", encoder=Base64Encoder)

        msg = smsg.message
        b64sig = smsg.signature

        sig = Base64Encoder.decode(b64sig)

        assert vk.verify(msg, sig, encoder=Base64Encoder) == \
            vk.verify(smsg, encoder=Base64Encoder)

        assert Base64Encoder.decode(msg) == b"Hello World in base64"
Ejemplo n.º 5
0
    def test_base64_smessage_with_detached_sig_matches_with_attached_sig(self):
        sk = SigningKey.generate()
        vk = sk.verify_key

        smsg = sk.sign(b"Hello World in base64", encoder=Base64Encoder)

        msg = smsg.message
        b64sig = smsg.signature

        sig = Base64Encoder.decode(b64sig)

        assert vk.verify(msg, sig, encoder=Base64Encoder) == \
            vk.verify(smsg, encoder=Base64Encoder)

        assert Base64Encoder.decode(msg) == b"Hello World in base64"
def read_file(file_name, base64=False):
    f = open(file_name, 'r')
    data = f.read()
    if base64:
        data = Base64Encoder.decode(data)
    f.close()
    return data
Ejemplo n.º 7
0
def verify_signature(webhook_uri,
                     signature_header,
                     signature_expiry_seconds=60):
    # v1 is signature, s is submissionId, f is formId, t is submission epoch
    logger.debug(f'X-FormSG-Signature is <{signature_header}>.')
    formsg_signature = dict(
        part.split('=', 1) for part in signature_header.split(','))
    formsg_signature['t'] = int(formsg_signature['t'])

    # Javascript url.href adds a trailing `/` to root domain urls
    # https://github.com/opengovsg/formsg-javascript-sdk/blob/master/src/webhooks.ts#L25
    u = urlparse(webhook_uri)
    if not u.path:
        u = u._replace(path='/')
    webhook_uri = u.geturl()

    FORMSG_WEBHOOK_PUBLIC_KEY.verify(
        smessage=
        f'{webhook_uri}.{formsg_signature["s"]}.{formsg_signature["f"]}.{formsg_signature["t"]}'
        .encode('ascii'),
        signature=Base64Encoder.decode(formsg_signature['v1']),
    )

    if time() - (formsg_signature['t'] / 1000) > signature_expiry_seconds:
        raise BadSignatureError('FormSG signature has expired.')

    return formsg_signature
    def handle(self, *args, **options):
        """Handle the command"""
        private_key = PrivateKey.generate()
        public_key = private_key.public_key

        self.stdout.write(
            '--------------------------------------------------------------')
        self.stdout.write('Private Key Base64 Encoded:')
        self.stdout.write(
            Base64Encoder.encode(bytes(private_key)).decode("utf-8"))
        self.stdout.write(
            '--------------------------------------------------------------')
        self.stdout.write('Public Key Base64 Encoded:')
        self.stdout.write(
            Base64Encoder.encode(bytes(public_key)).decode("utf-8"))
        self.stdout.write(
            '--------------------------------------------------------------')
Ejemplo n.º 9
0
 def _read_bytes_as_b64_from_file(self, file_path, silent=False):
     try:
         with open(file_path, 'r') as read_file:
             return Base64Encoder.decode(read_file.read())
     except Exception as e:
         if not silent:
             print(f'Opening file: {file_path}')
             print(e.args[1])
Ejemplo n.º 10
0
def set_user_password(tid, user, password, cc):
    # Regenerate the password hash only if different from the best choice on the platform
    if user.hash_alg != 'ARGON2':
        user.hash_alg = 'ARGON2'
        user.salt = GCE.generate_salt()

    password_hash = GCE.hash_password(password, user.salt)

    # Check that the new password is different form the current password
    if user.password == password_hash:
        raise errors.PasswordReuseError

    user.password = password_hash
    user.password_change_date = datetime_now()

    State.log(tid=tid,
              type='change_password',
              user_id=user.id,
              object_id=user.id)

    if not State.tenant_cache[tid].encryption and cc == '':
        return None

    enc_key = GCE.derive_key(password.encode(), user.salt)
    if not cc:
        # The first password change triggers the generation
        # of the user encryption private key and its backup
        cc, user.crypto_pub_key = GCE.generate_keypair()
        user.crypto_bkp_key, user.crypto_rec_key = GCE.generate_recovery_key(
            cc)

    user.crypto_prv_key = Base64Encoder.encode(
        GCE.symmetric_encrypt(enc_key, cc))

    if State.tenant_cache[1].crypto_escrow_pub_key:
        user.crypto_escrow_bkp1_key = Base64Encoder.encode(
            GCE.asymmetric_encrypt(State.tenant_cache[1].crypto_escrow_pub_key,
                                   cc))

    if State.tenant_cache[tid].crypto_escrow_pub_key:
        user.crypto_escrow_bkp2_key = Base64Encoder.encode(
            GCE.asymmetric_encrypt(
                State.tenant_cache[tid].crypto_escrow_pub_key, cc))

    return cc
Ejemplo n.º 11
0
    def decrypt(self, encrypted, sender_pub, recipient):
        box = Box(secret_key(recipient), public_key(sender_pub))
        if encrypted[:4] != 'msg:':
            raise DecryptionError

        try:
            return box.decrypt(Base64Encoder.decode(encrypted[4:]))
        except CryptoError:
            raise DecryptionError
Ejemplo n.º 12
0
def Decrypt_NaCl(Pk, Sk, nonce, ciphertext):
    Sk = PrivateKeyNaCl(Sk, encoder=Base64Encoder)
    Pk = PublicKeyNaCl(Pk, encoder=Base64Encoder)
    nonce = Base64Encoder.decode(nonce)
    box = BoxNaCl(Sk, Pk)
    # import numpy as np
    # print np.fromstring(box.shared_key(), dtype=np.uint8)
    plaintext = box.decrypt(ciphertext, nonce, encoder=Base64Encoder)
    return plaintext
Ejemplo n.º 13
0
 def _decrypt_and_set_private_key(self, private_key_store):
     if not self.password:
         raise AttributeError(
             'No password found! Password must be set ahead!')
     secure_key = pwhash.argon2i.kdf(secret.SecretBox.KEY_SIZE,
                                     Base64Encoder.decode(self.password),
                                     Base64Encoder.decode(
                                         private_key_store['salt']),
                                     opslimit=private_key_store['ops'],
                                     memlimit=private_key_store['mem'])
     encrypted = Base64Encoder.decode(private_key_store['private_key'])
     box = secret.SecretBox(secure_key)
     try:
         self.private_key = PrivateKey(box.decrypt(encrypted))
         self.public_key = self.private_key.public_key
         return True
     except Exception as e:
         print(e)
Ejemplo n.º 14
0
def invalid_settings():
    """
    Fixture that runs a test against a set of invalid configurations
    """
    settings = copy.copy(DEFAULT_SETTINGS)
    settings.update({
        'EXAMS_AUDIT_NACL_PUBLIC_KEY': Base64Encoder.encode('bad'),
    })

    with override_settings(**settings):
        yield settings
Ejemplo n.º 15
0
def valid_settings(private_key):
    """
    Fixture that provides valid (passes checks in configure()) configuration
    """
    settings = copy.copy(DEFAULT_SETTINGS)
    settings.update({
        'EXAMS_AUDIT_NACL_PUBLIC_KEY': Base64Encoder.encode(bytes(private_key.public_key)),
    })

    with override_settings(**settings):
        yield DEFAULT_SETTINGS
Ejemplo n.º 16
0
def invalid_settings():
    """
    Fixture that runs a test against a set of invalid configurations
    """
    settings = copy.copy(DEFAULT_SETTINGS)
    settings.update({
        'EXAMS_AUDIT_NACL_PUBLIC_KEY': Base64Encoder.encode('bad'),
    })

    with override_settings(**settings):
        yield settings
Ejemplo n.º 17
0
def valid_settings(private_key):
    """
    Fixture that provides valid (passes checks in configure()) configuration
    """
    settings = copy.copy(DEFAULT_SETTINGS)
    settings.update({
        'EXAMS_AUDIT_NACL_PUBLIC_KEY':
        Base64Encoder.encode(bytes(private_key.public_key)),
    })

    with override_settings(**settings):
        yield DEFAULT_SETTINGS
Ejemplo n.º 18
0
 def decrypt_text(self, cipher_text):
     if not self.private_key:
         self.import_private_key_from_file()
     if not self.private_key:
         raise AttributeError(
             'No private key known or found in file. Generate private key first!'
         )
     else:
         unseal_box = SealedBox(self.private_key)
         if re.fullmatch(self.CIPHER_PATTERN, cipher_text):
             cipher_text = re.search(self.CIPHER_PATTERN,
                                     cipher_text).group(1)
         return unseal_box.decrypt(
             Base64Encoder.decode(cipher_text)).decode('utf-8')
Ejemplo n.º 19
0
def get_auth(user_id, name, secret, nonce, method, uri, body=None):
    if body is not None:
        if not isinstance(body, str):
            try:
                body = json.dumps(body, separators=(',', ':'))
            except ValueError as e:
                logger.exception(
                    'invalid body. json or string are valid body type')
    request_string = '{"method":"' + method + '","uri":"' + uri + ('",' if (
        body is None) else '","body":' + body + ',') + '"nonce":' + nonce + '}'
    logger.debug("message %s", request_string)
    raw_signed = crypto_sign(request_string.encode(), bytes.fromhex(secret))
    signature = Base64Encoder.encode(raw_signed[:crypto_sign_BYTES])
    return 'SIGN ' + user_id + "." + name + ':' + signature.decode()
Ejemplo n.º 20
0
def get_recovery_key(session, tid, user_id, user_cc):
    """
    Transaction to get a user recovery key

    :param session: An ORM session
    :param tid: The tenant ID
    :param user_id: The user ID
    :param user_cc: The user key
    :return: The recovery key encoded base32
    """
    user = db_get_user(session, tid, user_id)

    if not user.crypto_rec_key:
        return ''

    user.clicked_recovery_key = True

    return Base32Encoder.encode(GCE.asymmetric_decrypt(user_cc, Base64Encoder.decode(user.crypto_rec_key.encode()))).replace(b'=', b'')
Ejemplo n.º 21
0
def get_cybersource_test_settings(private_key=None):
    """
    Generates a valid set of settings for CyberSource
    """
    if private_key is None:
        private_key = PrivateKey.generate()

    return {
        "CYBERSOURCE_WSDL_URL":
        (f"http://localhost/service/CyberSourceTransaction_{SERVICE_VERSION}.wsdl"
         ),
        "CYBERSOURCE_MERCHANT_ID":
        "merchant_id",
        "CYBERSOURCE_TRANSACTION_KEY":
        "transaction_key",
        "CYBERSOURCE_INQUIRY_LOG_NACL_ENCRYPTION_KEY":
        Base64Encoder.encode(bytes(private_key.public_key)),
    }
Ejemplo n.º 22
0
def decrypt_content(body_json, secret_key):
    if 'data' in body_json:
        encrypted_content = body_json['data']['encryptedContent']
    else:
        encrypted_content = body_json[
            'encryptedContent']  # old version POST body
    #end if

    submission_public_key, nonce, encrypted_message = ENCRYPTED_CONTENT_REGEX.match(
        encrypted_content).groups()

    box = Box(
        PrivateKey(secret_key, encoder=Base64Encoder),
        PublicKey(submission_public_key, encoder=Base64Encoder),
    )

    plaintext = box.decrypt(encrypted_message,
                            Base64Encoder.decode(nonce),
                            encoder=Base64Encoder)

    return json.loads(plaintext)
Ejemplo n.º 23
0
 def export_private_key_to_file(self):
     if not self.private_key:
         raise AttributeError(
             'No private key found to export. Generate or set private key first!'
         )
     else:
         salt = utils.random(pwhash.argon2i.SALTBYTES)
         secure_key = pwhash.argon2i.kdf(secret.SecretBox.KEY_SIZE,
                                         Base64Encoder.decode(
                                             self.password),
                                         salt,
                                         opslimit=self.ops,
                                         memlimit=self.mem)
         private_key_store = {
             'private_key': self._encrypt_private_key(secure_key),
             'salt': self._base64(salt),
             'ops': self.ops,
             'mem': self.mem
         }
         return self._write_dict_as_json_file(private_key_store,
                                              self.private_key_store)
Ejemplo n.º 24
0
def b2a(b):
    return Base64Encoder.encode(b)
Ejemplo n.º 25
0
 def _base64(self, data: bytes):
     return Base64Encoder.encode(data).decode('ASCII')
Ejemplo n.º 26
0
def fax_status_callback(request: HttpRequest):
    # get relevant signature data
    event_timestamp = request.headers.get("Telnyx-Timestamp")
    event_signature = request.headers.get("Telnyx-Signature-Ed25519")
    public_key = settings.TELNYX_PUBLIC_KEY

    # prepare signature data for nacl
    verify_key = VerifyKey(public_key, encoder=Base64Encoder)
    callback_bytes = f"{event_timestamp}|".encode("UTF-8") + request.body
    signature = Base64Encoder.decode(event_signature)

    # verify signature
    try:
        verify_key.verify(callback_bytes, signature=signature)
    except BadSignatureError:
        return HttpResponseForbidden("invalid signature",
                                     content_type="text/plain")

    payload_json = json.loads(request.body)

    # get message object
    fax_id = None
    try:
        fax_id = payload_json.get("data").get("payload").get("fax_id")
    except AttributeError as e:
        # this key should always exist. we should never end up here
        raise ValueError(
            f"This is not a valid API response body: {request.body}") from e

    if not fax_id:
        raise ValueError(
            f"This is not a valid API response body: {request.body}")

    fax_message: FoiMessage = get_object_or_404(FoiMessage,
                                                email_message_id=fax_id)

    # find status
    try:
        status = payload_json.get("data").get("payload").get("status")
    except AttributeError as e:
        # we should never end up here either
        raise ValueError(
            f"This is not a valid API response body: {request.body}") from e

    if status == "failed":
        status = DeliveryStatus.Delivery.STATUS_FAILED
    elif status == "queued":
        status = DeliveryStatus.Delivery.STATUS_SENDING
    elif status == "media.processed":
        status = DeliveryStatus.Delivery.STATUS_SENDING
    elif status.startswith("sending"):
        status = DeliveryStatus.Delivery.STATUS_SENDING
    elif status == "delivered":
        status = DeliveryStatus.Delivery.STATUS_SENT
    else:
        # again: we should not end up here. according to telnyx-docu those are all possible stati
        raise ValueError(f"This is not a valid status response: {status}")

    # only try and update if the timestamp in request is more recent than the one in the database
    dt = datetime.datetime.fromtimestamp(int(event_timestamp),
                                         pytz.timezone("UTC"))
    if fax_message.deliverystatus.last_update > dt:
        return HttpResponse(status=409)

    ds, _created = DeliveryStatus.objects.update_or_create(
        message=fax_message,
        defaults=dict(
            status=status,
            last_update=timezone.now(),
        ),
    )
    data = payload_json.get("data")

    # Create machine-readable log
    fax_log_data = {
        "from_": data["payload"]["from"],
        "to": data["payload"]["to"],
        "sid": data["payload"]["fax_id"],
        "status": data["payload"]["status"],
        "num_pages": data["payload"].get("page_count", 0),
        "duration": data["payload"].get("call_duration_secs", 0),
        "failure_reason": data["payload"].get("failure_reason"),
        "date_created": data["occurred_at"],
    }
    ds.log = create_fax_log(ds.log, fax_log_data)
    ds.save()

    if status == DeliveryStatus.Delivery.STATUS_SENT:
        fax_message.timestamp = ds.last_update
        fax_message.save()
        ProblemReport.objects.find_and_resolve(
            message=fax_message, kind=ProblemReport.PROBLEM.BOUNCE_PUBLICBODY)

    failed = False
    if status == DeliveryStatus.Delivery.STATUS_FAILED:
        if ds.retry_count >= 3:
            failed = True
        else:
            # Retry fax delivery in 15 minutes
            retry_fax_delivery.apply_async(
                (fax_message.pk, ),
                {},
                # resend in intervals of 0.25, 1, 2 and 4 hours
                countdown=15 * 60 * 4**ds.retry_count,
            )

    if failed:
        ProblemReport.objects.report(
            message=fax_message,
            kind=ProblemReport.PROBLEM.BOUNCE_PUBLICBODY,
            description=ds.log,
            auto_submitted=True,
        )

    return HttpResponse(status=200)
Ejemplo n.º 27
0
 def set_public_key(self, b64_public_key):
     self.public_key = PublicKey(Base64Encoder.decode(b64_public_key))
Ejemplo n.º 28
0
################################################################################
# BEGIN MOCKS NECESSARY FOR DETERMINISTIC ENCRYPTION
VALID_PASSWORD1 = 'ACollectionOfDiplomaticHistorySince_1966_ToThe_Pr esentDay#'
VALID_PASSWORD2 = VALID_PASSWORD1
VALID_SALT1 = GCE.generate_salt()
VALID_SALT2 = GCE.generate_salt()
VALID_HASH1 = GCE.hash_password(VALID_PASSWORD1, VALID_SALT1)
VALID_HASH2 = GCE.hash_password(VALID_PASSWORD2, VALID_SALT2)
VALID_BASE64_IMG = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII='
INVALID_PASSWORD = '******'

KEY = GCE.generate_key()
USER_KEY = GCE.derive_key(VALID_PASSWORD1, VALID_SALT1)
USER_PRV_KEY, USER_PUB_KEY = GCE.generate_keypair()
USER_PRV_KEY_ENC = Base64Encoder.encode(
    GCE.symmetric_encrypt(USER_KEY, USER_PRV_KEY))
USER_BKP_KEY, USER_REC_KEY = GCE.generate_recovery_key(USER_PRV_KEY)
USER_REC_KEY_PLAIN = GCE.asymmetric_decrypt(USER_PRV_KEY,
                                            Base64Encoder.decode(USER_REC_KEY))
USER_REC_KEY_PLAIN = Base32Encoder.encode(USER_REC_KEY_PLAIN).replace(
    b'=', b'').decode('utf-8')
GCE_orig_generate_key = GCE.generate_key
GCE_orig_generate_keypair = GCE.generate_keypair


def mock_nullfunction(*args, **kwargs):
    return


def mock_GCE_generate_key():
    return KEY
Ejemplo n.º 29
0
message = 'abcdefg1234'
encoding = 'utf-8'

print('-' * 100)
print('KEY and MESSAGE')
print('-' * 100)
print('PRIKEY:', prikey)
print('PRIKEY(BASE64):', prikey.encode(Base64Encoder).decode(encoding))
print('PUBKEY:', pubkey)
print('PUBKEY(BASE64):', pubkey.encode(Base64Encoder).decode(encoding))
print('MESSAGE:', message)

print('-' * 100)
print('ENCRYPT with public key')
print('-' * 100)

box = SealedBox(pubkey)
encrypted = box.encrypt(message.encode(encoding=encoding))
print('ENCRYPTED MESSAGE:', encrypted)
print('ENCRYPTED MESSAGE(BASE64):',
      Base64Encoder.encode(encrypted).decode(encoding))

print('-' * 100)
print('DECRYPT with private key')
print('-' * 100)

box = SealedBox(prikey)
decrypted = box.decrypt(encrypted).decode(encoding=encoding)
print('DECRYPTED MESSAGE:', decrypted)
Ejemplo n.º 30
0
def a2b(a):
    return Base64Encoder.decode(a)
Ejemplo n.º 31
0
 def challenge(self):
     return Base64Encoder.encode(self.nonce())
Ejemplo n.º 32
0
def b2a(b):
    return Base64Encoder.encode(b)
Ejemplo n.º 33
0
def a2b(a):
    return Base64Encoder.decode(a)
def write_file(file_name, data, base64=False):
    if base64:
        data = Base64Encoder.encode(data).decode('ascii')
    f = open(file_name, 'w')
    f.write(data)
    f.close()