Last active
September 28, 2021 15:46
-
-
Save SaveTheRbtz/246eab8557b0217ab3945e15cef6ffe8 to your computer and use it in GitHub Desktop.
DEG2021
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
# Generated by the protocol buffer compiler. DO NOT EDIT! | |
# source: choices.proto | |
"""Generated protocol buffer code.""" | |
from google.protobuf import descriptor as _descriptor | |
from google.protobuf import message as _message | |
from google.protobuf import reflection as _reflection | |
from google.protobuf import symbol_database as _symbol_database | |
# @@protoc_insertion_point(imports) | |
_sym_db = _symbol_database.Default() | |
DESCRIPTOR = _descriptor.FileDescriptor( | |
name='choices.proto', | |
package='', | |
syntax='proto3', | |
serialized_options=None, | |
create_key=_descriptor._internal_create_key, | |
serialized_pb=b'\n\rchoices.proto\"\x17\n\x07\x43hoices\x12\x0c\n\x04\x64\x61ta\x18\x01 \x03(\rb\x06proto3' | |
) | |
_CHOICES = _descriptor.Descriptor( | |
name='Choices', | |
full_name='Choices', | |
filename=None, | |
file=DESCRIPTOR, | |
containing_type=None, | |
create_key=_descriptor._internal_create_key, | |
fields=[ | |
_descriptor.FieldDescriptor( | |
name='data', full_name='Choices.data', index=0, | |
number=1, type=13, cpp_type=3, label=3, | |
has_default_value=False, default_value=[], | |
message_type=None, enum_type=None, containing_type=None, | |
is_extension=False, extension_scope=None, | |
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), | |
], | |
extensions=[ | |
], | |
nested_types=[], | |
enum_types=[ | |
], | |
serialized_options=None, | |
is_extendable=False, | |
syntax='proto3', | |
extension_ranges=[], | |
oneofs=[ | |
], | |
serialized_start=17, | |
serialized_end=40, | |
) | |
DESCRIPTOR.message_types_by_name['Choices'] = _CHOICES | |
_sym_db.RegisterFileDescriptor(DESCRIPTOR) | |
Choices = _reflection.GeneratedProtocolMessageType('Choices', (_message.Message,), { | |
'DESCRIPTOR' : _CHOICES, | |
'__module__' : 'choices_pb2' | |
# @@protoc_insertion_point(class_scope:Choices) | |
}) | |
_sym_db.RegisterMessage(Choices) | |
# @@protoc_insertion_point(module_scope) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import psycopg2 | |
import psycopg2.extras | |
import json | |
import six | |
import nacl.utils | |
from nacl.public import PrivateKey, PublicKey, Box | |
from choices_pb2 import Choices | |
# XXX: enc = {...} | |
skey = PrivateKey(bytes.fromhex("54e3cf70f712b2ff727bde3849772fa811a9d5de796aa7d788d205aa86af04ad")) | |
pkey = PublicKey(bytes.fromhex(enc['public_key'])) | |
box = Box(skey, pkey) | |
pb = box.decrypt(bytes.fromhex(enc['encrypted_message']), bytes.fromhex(enc['nonce'])) | |
offset = int.from_bytes(pb[:2], 'big')+2 | |
choices = Choices().FromString(pb[offset:]) | |
print(choices.data) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"id": "7fa0a2c5", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"import psycopg2\n", | |
"import psycopg2.extras\n", | |
"\n", | |
"import json\n", | |
"import six\n", | |
"\n", | |
"import nacl.utils\n", | |
"from nacl.public import PrivateKey, PublicKey, Box\n", | |
"\n", | |
"\n", | |
"from choices_pb2 import Choices" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"id": "c88d654f", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"conn = psycopg2.connect(\n", | |
" host=\"localhost\",\n", | |
" database=\"rbtz\")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"id": "fea298e4", | |
"metadata": { | |
"scrolled": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"An error occurred trying to decrypt the message\n", | |
"['f07ee512b57bc7d6176592ee6a4ab2526c025af2d57cd9e636c038e61b57db06', '0aaf010aac010a0508e907100612a2010a406561303637653161643731353635646166663535363237653462333533343036323064353364363434383230343738656537393865313235656665363537633210d2011a5b0a193631b09b2513132340eda2d5905756c8dd0d4351b0897e0594121a0a1866805830f3a11d610c99b841b22bc71c69227fc6bc9983f11a220a20206c03a67246410a3c992ca13aa005fc68ea70b7ac97f2e4c7e86f2697ba641b12220a204bd18b3c8f94c88f222fd4061e469148623b97b5713ecc8712a4829538535fc51a420a40693b252df5448f8479567580f064a26af1b379e6177357067fbf10fb486d9431aa38fae9a7c3e0a7c6bebb27ff5e517b2e155a445704b5da2d858bbb7443e302', 166209, 45, {'proof': [{'index': 44, 'height': 1, 'hash': '637c2bccae331bc297ce03bdc71ab3a73740fd8567a742c69de73098c9cb2ac7'}, {'index': 23, 'height': 2, 'hash': '9711500714314f94c9b72c58cbe32cfdb02b09c9fc2c4c3e02880b9c111524ce'}, {'index': 10, 'height': 3, 'hash': '58c4d556dc854b76560ec6e11822a4e02cffef28645d53b68ae5cdb107a7f013'}, {'index': 4, 'height': 4, 'hash': '288510ba24dd8cae59dc604a168d4e833050361a23cb853bb101d8c23f8871b3'}, {'index': 3, 'height': 5, 'hash': 'e68e5e327e3d5514551eab1b764d9f01707594603d077f6fca182c19990553d2'}, {'index': 0, 'height': 6, 'hash': '3340b2c70183beab261fc5ff3b9d04695054268e33d190748c5929b59ca38b5e'}], 'entries': [[45, 'f07ee512b57bc7d6176592ee6a4ab2526c025af2d57cd9e636c038e61b57db06']], 'length': 49}, 1001, 6, {'type': 'success'}, datetime.datetime(2021, 9, 17, 10, 8, 2, 608000, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=61200))), '4bd18b3c8f94c88f222fd4061e469148623b97b5713ecc8712a4829538535fc5', {'voting_id': 'ea067e1ad71565daff55627e4b35340620d53d644820478ee798e125efe657c2', 'district_id': 210, 'encrypted_choice': {'encrypted_message': '3631b09b2513132340eda2d5905756c8dd0d4351b0897e0594', 'nonce': '66805830f3a11d610c99b841b22bc71c69227fc6bc9983f1', 'public_key': '206c03a67246410a3c992ca13aa005fc68ea70b7ac97f2e4c7e86f2697ba641b'}}, '693b252df5448f8479567580f064a26af1b379e6177357067fbf10fb486d9431aa38fae9a7c3e0a7c6bebb27ff5e517b2e155a445704b5da2d858bbb7443e302', None]\n" | |
] | |
}, | |
{ | |
"ename": "KeyboardInterrupt", | |
"evalue": "", | |
"output_type": "error", | |
"traceback": [ | |
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", | |
"\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", | |
"\u001b[0;32m/tmp/ipykernel_55390/998520914.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0mskey\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mPrivateKey\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbytes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfromhex\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"54e3cf70f712b2ff727bde3849772fa811a9d5de796aa7d788d205aa86af04ad\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0mpkey\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mPublicKey\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbytes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfromhex\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0menc\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'public_key'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m \u001b[0mbox\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mBox\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mskey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 11\u001b[0m \u001b[0mpb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mbox\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdecrypt\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbytes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfromhex\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0menc\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'encrypted_message'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbytes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfromhex\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0menc\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'nonce'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0moffset\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mint\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfrom_bytes\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpb\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'big'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m+\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;32m/usr/lib/python3.9/site-packages/nacl/public.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, private_key, public_key)\u001b[0m\n\u001b[1;32m 177\u001b[0m raise exc.TypeError(\"Box must be created from \"\n\u001b[1;32m 178\u001b[0m \"a PrivateKey and a PublicKey\")\n\u001b[0;32m--> 179\u001b[0;31m self._shared_key = nacl.bindings.crypto_box_beforenm(\n\u001b[0m\u001b[1;32m 180\u001b[0m \u001b[0mpublic_key\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mencode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mencoder\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mencoding\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mRawEncoder\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 181\u001b[0m \u001b[0mprivate_key\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mencode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mencoder\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mencoding\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mRawEncoder\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;32m/usr/lib/python3.9/site-packages/nacl/bindings/crypto_box.py\u001b[0m in \u001b[0;36mcrypto_box_beforenm\u001b[0;34m(pk, sk)\u001b[0m\n\u001b[1;32m 170\u001b[0m \u001b[0mk\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mffi\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnew\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"unsigned char[]\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcrypto_box_BEFORENMBYTES\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 171\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 172\u001b[0;31m \u001b[0mrc\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlib\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcrypto_box_beforenm\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpk\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msk\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 173\u001b[0m ensure(rc == 0,\n\u001b[1;32m 174\u001b[0m \u001b[0;34m'Unexpected library error'\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;31mKeyboardInterrupt\u001b[0m: " | |
] | |
} | |
], | |
"source": [ | |
"cur = conn.cursor(cursor_factory = psycopg2.extras.DictCursor)\n", | |
"cur.execute(\"select * from transactions where method_id=6\")\n", | |
"for i, row in enumerate(cur):\n", | |
" try:\n", | |
" enc = row['payload']['encrypted_choice']\n", | |
" #print(row)\n", | |
" #print(row['hash'], row['payload']['encrypted_choice'])\n", | |
" skey = PrivateKey(bytes.fromhex(\"54e3cf70f712b2ff727bde3849772fa811a9d5de796aa7d788d205aa86af04ad\"))\n", | |
" pkey = PublicKey(bytes.fromhex(enc['public_key']))\n", | |
" box = Box(skey, pkey)\n", | |
" pb = box.decrypt(bytes.fromhex(enc['encrypted_message']), bytes.fromhex(enc['nonce']))\n", | |
" offset = int.from_bytes(pb[:2], 'big')+2\n", | |
" choices = Choices().FromString(pb[offset:])\n", | |
" cur2 = conn.cursor()\n", | |
" cur2.execute(f\"select * from decrypted_ballots where store_tx_hash='{row['hash']}'\")\n", | |
" if cur2.rowcount == 0:\n", | |
" sql = f\"\"\"INSERT INTO decrypted_ballots(store_tx_hash,decrypted_choice,status)\n", | |
" VALUES('{row['hash']}',array[{choices.data[0]}]::bigint[],'\"Manual\"');\"\"\"\n", | |
" cur2.execute(sql)\n", | |
" conn.commit()\n", | |
" except Exception as e:\n", | |
" print (e)\n", | |
" print (row)\n" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"id": "255560ec", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"ename": "CryptoError", | |
"evalue": "An error occurred trying to decrypt the message", | |
"output_type": "error", | |
"traceback": [ | |
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", | |
"\u001b[0;31mCryptoError\u001b[0m Traceback (most recent call last)", | |
"\u001b[0;32m/tmp/ipykernel_55390/2992075636.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mpkey\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mPublicKey\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbytes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfromhex\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'206c03a67246410a3c992ca13aa005fc68ea70b7ac97f2e4c7e86f2697ba641b'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mbox\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mBox\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mskey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0mpb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mbox\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdecrypt\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbytes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfromhex\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'3631b09b2513132340eda2d5905756c8dd0d4351b0897e0594'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbytes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfromhex\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'66805830f3a11d610c99b841b22bc71c69227fc6bc9983f1'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", | |
"\u001b[0;32m/usr/lib/python3.9/site-packages/nacl/public.py\u001b[0m in \u001b[0;36mdecrypt\u001b[0;34m(self, ciphertext, nonce, encoder)\u001b[0m\n\u001b[1;32m 258\u001b[0m self.NONCE_SIZE)\n\u001b[1;32m 259\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 260\u001b[0;31m plaintext = nacl.bindings.crypto_box_open_afternm(\n\u001b[0m\u001b[1;32m 261\u001b[0m \u001b[0mciphertext\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 262\u001b[0m \u001b[0mnonce\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;32m/usr/lib/python3.9/site-packages/nacl/bindings/crypto_box.py\u001b[0m in \u001b[0;36mcrypto_box_open_afternm\u001b[0;34m(ciphertext, nonce, k)\u001b[0m\n\u001b[1;32m 226\u001b[0m res = lib.crypto_box_open_afternm(\n\u001b[1;32m 227\u001b[0m plaintext, padded, len(padded), nonce, k)\n\u001b[0;32m--> 228\u001b[0;31m ensure(res == 0, \"An error occurred trying to decrypt the message\",\n\u001b[0m\u001b[1;32m 229\u001b[0m raising=exc.CryptoError)\n\u001b[1;32m 230\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", | |
"\u001b[0;32m/usr/lib/python3.9/site-packages/nacl/exceptions.py\u001b[0m in \u001b[0;36mensure\u001b[0;34m(cond, *args, **kwds)\u001b[0m\n\u001b[1;32m 79\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mcond\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 80\u001b[0m \u001b[0;32mreturn\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 81\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mraising\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", | |
"\u001b[0;31mCryptoError\u001b[0m: An error occurred trying to decrypt the message" | |
] | |
} | |
], | |
"source": [ | |
"skey = PrivateKey(bytes.fromhex(\"54e3cf70f712b2ff727bde3849772fa811a9d5de796aa7d788d205aa86af04ad\"))\n", | |
"pkey = PublicKey(bytes.fromhex('206c03a67246410a3c992ca13aa005fc68ea70b7ac97f2e4c7e86f2697ba641b'))\n", | |
"box = Box(skey, pkey)\n", | |
"pb = box.decrypt(bytes.fromhex('3631b09b2513132340eda2d5905756c8dd0d4351b0897e0594'), bytes.fromhex('66805830f3a11d610c99b841b22bc71c69227fc6bc9983f1'))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "4ddad925", | |
"metadata": {}, | |
"outputs": [], | |
"source": [] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 3 (ipykernel)", | |
"language": "python", | |
"name": "python3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.9.7" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 5 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment