def decrypt(cls, token: bytes, key: bytes) -> dict: parts = token.split(b'.') footer = b'' if len(parts) == 4: encoded_footer = parts[-1] footer = b64decode(encoded_footer) header_len = len(cls.local_header) header = token[:header_len] token_version = token[:2] if not secrets.compare_digest(token_version, cls.version): raise InvalidVersionException('not a v2 token') if not secrets.compare_digest(header, cls.local_header): raise InvalidPurposeException('not a v2.local token') decoded = b64decode(parts[2]) nonce = decoded[:pysodium.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES] ciphertext = decoded[pysodium.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES:] plaintext = pysodium.crypto_aead_xchacha20poly1305_ietf_decrypt( ciphertext=ciphertext, ad=pre_auth_encode(header, nonce, footer), nonce=nonce, key=key ) return { 'message': plaintext, 'footer': footer if footer else None }
def test_aead_xchacha20poly1305_ietf(self): if not pysodium.sodium_version_check(1, 0, 12): return key = binascii.unhexlify(b"4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd1100a1007") input_ = binascii.unhexlify(b"86d09974840bded2a5ca") nonce = binascii.unhexlify(b"cd7cf67be39c794acd7cf67bcd7cf67be39c794acd7cf67b") for ad in [binascii.unhexlify(b"87e229d4500845a079c0"), None]: output = pysodium.crypto_aead_xchacha20poly1305_ietf_encrypt(input_, ad, nonce, key) output = pysodium.crypto_aead_xchacha20poly1305_ietf_decrypt(output, ad, nonce, key) self.assertEqual(output, input_)
def test_aead_xchacha20poly1305_ietf(self): if not pysodium.sodium_version_check(1, 0, 12): return key = binascii.unhexlify(b"4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd1100a1007") input_ = binascii.unhexlify(b"86d09974840bded2a5ca") nonce = binascii.unhexlify(b"cd7cf67be39c794acd7cf67bcd7cf67be39c794acd7cf67b") for ad in [binascii.unhexlify(b"87e229d4500845a079c0"), None]: output = pysodium.crypto_aead_xchacha20poly1305_ietf_encrypt(input_, ad, nonce, key) output = pysodium.crypto_aead_xchacha20poly1305_ietf_decrypt(output, ad, nonce, key) self.assertEqual(output, input_)
def decrypt(ciphertext: bytes, key: bytes): if not secrets.compare_digest(ciphertext[:5], MAGIC_HEADER): raise Exception('Invalid ciphertext header') decoded = base64.urlsafe_b64decode(ciphertext[5:]) if len(decoded) < NONCE_SIZE + 16: raise Exception('Message is too short') nonce = decoded[0:NONCE_SIZE] encrypted = decoded[NONCE_SIZE:] decrypted = pysodium.crypto_aead_xchacha20poly1305_ietf_decrypt( ciphertext=encrypted, ad=nonce, nonce=nonce, key=key, ) return decrypted
def get_pdf(modeladmin, request, queryset): documents = [] response = HttpResponse(content_type="application/pdf") for wallet in queryset.all(): encryption_key = bytes.fromhex(settings.ENCRYPTION_KEY) nonce = pysodium.randombytes(pysodium.crypto_secretbox_NONCEBYTES) pk = pysodium.crypto_aead_xchacha20poly1305_ietf_encrypt( wallet.private_key.encode('UTF-8'), None, nonce, encryption_key) decrypted_pk = pysodium.crypto_aead_xchacha20poly1305_ietf_decrypt( pk, None, nonce, encryption_key) payload = { 'nonce': nonce.hex(), 'id': wallet.wallet_id, 'pk': pk.hex() } qr_code = pyqrcode.create(json.dumps(payload), error='M') template = get_template('wallet/paper_wallet_pdf.html') html = template.render( { 'image': qr_code.png_as_base64_str(scale=5), 'logo': settings.STATIC_ROOT + '/wallet/ecoo_logo_bw.png', 'wetzikon_bw': settings.STATIC_ROOT + '/wallet/wetzikon_bw.png' }, request) # .encode(encoding="UTF-8") documents.append( weasyprint.HTML( string=html, base_url=request.build_absolute_uri()).write_pdf( target=response, presentational_hints=True, stylesheets=[ CSS(settings.STATIC_ROOT + '/wallet/print.css') ])) return response