Skip to content

Commit 8e3dc82

Browse files
committed
Set up pubnub
1 parent 076389c commit 8e3dc82

805 files changed

Lines changed: 437842 additions & 3 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

backend/app/__init__.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,24 @@
1-
from flask import Flask
1+
from flask import Flask, jsonify
2+
3+
from backend.blockchain.blockchain import Blockchain
24

35
app = Flask(__name__)
6+
blockchain = Blockchain()
47

58
@app.route('/')
6-
def default():
9+
def route_default():
710
return 'Welcome to the blockchain'
811

12+
@app.route('/blockchain')
13+
def route_blockchain():
14+
return jsonify(blockchain.to_json())
15+
16+
@app.route('/blockchain/mine')
17+
def route_blockchain_mine():
18+
transaction_data = 'stubbed_transaction_data'
19+
20+
blockchain.add_block(transaction_data)
21+
22+
return jsonify(blockchain.chain[-1].to_json())
23+
924
app.run()

backend/blockchain/block.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ def __repr__(self):
4040
def __eq__(self, other):
4141
return self.__dict__ == other.__dict__
4242

43+
def to_json(self):
44+
"""
45+
Serialize the block into a dictionary of its attributes
46+
"""
47+
return self.__dict__
48+
4349
@staticmethod
4450
def mine_block(last_block, data):
4551
"""

backend/blockchain/blockchain.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ def replace_chain(self, chain):
3030

3131
self.chain = chain
3232

33+
def to_json(self):
34+
"""
35+
Serialize the blockchain into a list of blocks.
36+
"""
37+
return list(map(lambda block: block.to_json(), self.chain))
38+
3339
@staticmethod
3440
def is_valid_chain(chain):
3541
"""

backend/pubsub.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import time
2+
3+
from pubnub.pubnub import PubNub
4+
from pubnub.pnconfiguration import PNConfiguration
5+
from pubnub.callbacks import SubscribeCallback
6+
7+
pnconfig = PNConfiguration()
8+
pnconfig.subscribe_key = 'sub-c-666638f6-ec63-11e9-b715-9abbdb5d0da2'
9+
pnconfig.publish_key = 'pub-c-82bf7695-ce5e-4bc5-9cd9-a8f8147dc2a8'
10+
pubnub = PubNub(pnconfig)
11+
12+
TEST_CHANNEL = 'TEST_CHANNEL'
13+
14+
pubnub.subscribe().channels([TEST_CHANNEL]).execute()
15+
16+
class Listener(SubscribeCallback):
17+
def message(self, pubnub, message_object):
18+
print(f'\n-- Incoming message_object: {message_object}')
19+
20+
21+
pubnub.add_listener(Listener())
22+
23+
def main():
24+
time.sleep(1)
25+
26+
pubnub.publish().channel(TEST_CHANNEL).message({ 'foo': 'bar' }).sync()
27+
28+
if __name__ == '__main__':
29+
main()

blockchain-env/bin/chardetect

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/Users/david/Code/python-blockchain/blockchain-env/bin/python3
2+
# -*- coding: utf-8 -*-
3+
import re
4+
import sys
5+
6+
from chardet.cli.chardetect import main
7+
8+
if __name__ == '__main__':
9+
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
10+
sys.exit(main())
Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# Cipher/AES.py : AES
4+
#
5+
# ===================================================================
6+
# The contents of this file are dedicated to the public domain. To
7+
# the extent that dedication to the public domain is not available,
8+
# everyone is granted a worldwide, perpetual, royalty-free,
9+
# non-exclusive license to exercise all rights associated with the
10+
# contents of this file for any purpose whatsoever.
11+
# No rights are reserved.
12+
#
13+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
15+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
17+
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
18+
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
# SOFTWARE.
21+
# ===================================================================
22+
"""
23+
Module's constants for the modes of operation supported with AES:
24+
25+
:var MODE_ECB: :ref:`Electronic Code Book (ECB) <ecb_mode>`
26+
:var MODE_CBC: :ref:`Cipher-Block Chaining (CBC) <cbc_mode>`
27+
:var MODE_CFB: :ref:`Cipher FeedBack (CFB) <cfb_mode>`
28+
:var MODE_OFB: :ref:`Output FeedBack (OFB) <ofb_mode>`
29+
:var MODE_CTR: :ref:`CounTer Mode (CTR) <ctr_mode>`
30+
:var MODE_OPENPGP: :ref:`OpenPGP Mode <openpgp_mode>`
31+
:var MODE_CCM: :ref:`Counter with CBC-MAC (CCM) Mode <ccm_mode>`
32+
:var MODE_EAX: :ref:`EAX Mode <eax_mode>`
33+
:var MODE_GCM: :ref:`Galois Counter Mode (GCM) <gcm_mode>`
34+
:var MODE_SIV: :ref:`Syntethic Initialization Vector (SIV) <siv_mode>`
35+
:var MODE_OCB: :ref:`Offset Code Book (OCB) <ocb_mode>`
36+
"""
37+
38+
import sys
39+
40+
from Cryptodome.Cipher import _create_cipher
41+
from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib,
42+
VoidPointer, SmartPointer,
43+
c_size_t, c_uint8_ptr)
44+
45+
from Cryptodome.Util import _cpu_features
46+
from Cryptodome.Random import get_random_bytes
47+
48+
49+
_cproto = """
50+
int AES_start_operation(const uint8_t key[],
51+
size_t key_len,
52+
void **pResult);
53+
int AES_encrypt(const void *state,
54+
const uint8_t *in,
55+
uint8_t *out,
56+
size_t data_len);
57+
int AES_decrypt(const void *state,
58+
const uint8_t *in,
59+
uint8_t *out,
60+
size_t data_len);
61+
int AES_stop_operation(void *state);
62+
"""
63+
64+
65+
# Load portable AES
66+
_raw_aes_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._raw_aes",
67+
_cproto)
68+
69+
# Try to load AES with AES NI instructions
70+
try:
71+
_raw_aesni_lib = None
72+
if _cpu_features.have_aes_ni():
73+
_raw_aesni_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._raw_aesni",
74+
_cproto.replace("AES",
75+
"AESNI"))
76+
# _raw_aesni may not have been compiled in
77+
except OSError:
78+
pass
79+
80+
81+
def _create_base_cipher(dict_parameters):
82+
"""This method instantiates and returns a handle to a low-level
83+
base cipher. It will absorb named parameters in the process."""
84+
85+
use_aesni = dict_parameters.pop("use_aesni", True)
86+
87+
try:
88+
key = dict_parameters.pop("key")
89+
except KeyError:
90+
raise TypeError("Missing 'key' parameter")
91+
92+
if len(key) not in key_size:
93+
raise ValueError("Incorrect AES key length (%d bytes)" % len(key))
94+
95+
if use_aesni and _raw_aesni_lib:
96+
start_operation = _raw_aesni_lib.AESNI_start_operation
97+
stop_operation = _raw_aesni_lib.AESNI_stop_operation
98+
else:
99+
start_operation = _raw_aes_lib.AES_start_operation
100+
stop_operation = _raw_aes_lib.AES_stop_operation
101+
102+
cipher = VoidPointer()
103+
result = start_operation(c_uint8_ptr(key),
104+
c_size_t(len(key)),
105+
cipher.address_of())
106+
if result:
107+
raise ValueError("Error %X while instantiating the AES cipher"
108+
% result)
109+
return SmartPointer(cipher.get(), stop_operation)
110+
111+
112+
def _derive_Poly1305_key_pair(key, nonce):
113+
"""Derive a tuple (r, s, nonce) for a Poly1305 MAC.
114+
115+
If nonce is ``None``, a new 16-byte nonce is generated.
116+
"""
117+
118+
if len(key) != 32:
119+
raise ValueError("Poly1305 with AES requires a 32-byte key")
120+
121+
if nonce is None:
122+
nonce = get_random_bytes(16)
123+
elif len(nonce) != 16:
124+
raise ValueError("Poly1305 with AES requires a 16-byte nonce")
125+
126+
s = new(key[:16], MODE_ECB).encrypt(nonce)
127+
return key[16:], s, nonce
128+
129+
130+
def new(key, mode, *args, **kwargs):
131+
"""Create a new AES cipher.
132+
133+
:param key:
134+
The secret key to use in the symmetric cipher.
135+
136+
It must be 16, 24 or 32 bytes long (respectively for *AES-128*,
137+
*AES-192* or *AES-256*).
138+
139+
For ``MODE_SIV`` only, it doubles to 32, 48, or 64 bytes.
140+
:type key: bytes/bytearray/memoryview
141+
142+
:param mode:
143+
The chaining mode to use for encryption or decryption.
144+
If in doubt, use ``MODE_EAX``.
145+
:type mode: One of the supported ``MODE_*`` constants
146+
147+
:Keyword Arguments:
148+
* **iv** (*bytes*, *bytearray*, *memoryview*) --
149+
(Only applicable for ``MODE_CBC``, ``MODE_CFB``, ``MODE_OFB``,
150+
and ``MODE_OPENPGP`` modes).
151+
152+
The initialization vector to use for encryption or decryption.
153+
154+
For ``MODE_CBC``, ``MODE_CFB``, and ``MODE_OFB`` it must be 16 bytes long.
155+
156+
For ``MODE_OPENPGP`` mode only,
157+
it must be 16 bytes long for encryption
158+
and 18 bytes for decryption (in the latter case, it is
159+
actually the *encrypted* IV which was prefixed to the ciphertext).
160+
161+
If not provided, a random byte string is generated (you must then
162+
read its value with the :attr:`iv` attribute).
163+
164+
* **nonce** (*bytes*, *bytearray*, *memoryview*) --
165+
(Only applicable for ``MODE_CCM``, ``MODE_EAX``, ``MODE_GCM``,
166+
``MODE_SIV``, ``MODE_OCB``, and ``MODE_CTR``).
167+
168+
A value that must never be reused for any other encryption done
169+
with this key (except possibly for ``MODE_SIV``, see below).
170+
171+
For ``MODE_EAX``, ``MODE_GCM`` and ``MODE_SIV`` there are no
172+
restrictions on its length (recommended: **16** bytes).
173+
174+
For ``MODE_CCM``, its length must be in the range **[7..13]**.
175+
Bear in mind that with CCM there is a trade-off between nonce
176+
length and maximum message size. Recommendation: **11** bytes.
177+
178+
For ``MODE_OCB``, its length must be in the range **[1..15]**
179+
(recommended: **15**).
180+
181+
For ``MODE_CTR``, its length must be in the range **[0..15]**
182+
(recommended: **8**).
183+
184+
For ``MODE_SIV``, the nonce is optional, if it is not specified,
185+
then no nonce is being used, which renders the encryption
186+
deterministic.
187+
188+
If not provided, for modes other than ``MODE_SIV```, a random
189+
byte string of the recommended length is used (you must then
190+
read its value with the :attr:`nonce` attribute).
191+
192+
* **segment_size** (*integer*) --
193+
(Only ``MODE_CFB``).The number of **bits** the plaintext and ciphertext
194+
are segmented in. It must be a multiple of 8.
195+
If not specified, it will be assumed to be 8.
196+
197+
* **mac_len** : (*integer*) --
198+
(Only ``MODE_EAX``, ``MODE_GCM``, ``MODE_OCB``, ``MODE_CCM``)
199+
Length of the authentication tag, in bytes.
200+
201+
It must be even and in the range **[4..16]**.
202+
The recommended value (and the default, if not specified) is **16**.
203+
204+
* **msg_len** : (*integer*) --
205+
(Only ``MODE_CCM``). Length of the message to (de)cipher.
206+
If not specified, ``encrypt`` must be called with the entire message.
207+
Similarly, ``decrypt`` can only be called once.
208+
209+
* **assoc_len** : (*integer*) --
210+
(Only ``MODE_CCM``). Length of the associated data.
211+
If not specified, all associated data is buffered internally,
212+
which may represent a problem for very large messages.
213+
214+
* **initial_value** : (*integer* or *bytes/bytearray/memoryview*) --
215+
(Only ``MODE_CTR``).
216+
The initial value for the counter. If not present, the cipher will
217+
start counting from 0. The value is incremented by one for each block.
218+
The counter number is encoded in big endian mode.
219+
220+
* **counter** : (*object*) --
221+
Instance of ``Cryptodome.Util.Counter``, which allows full customization
222+
of the counter block. This parameter is incompatible to both ``nonce``
223+
and ``initial_value``.
224+
225+
* **use_aesni** : (*boolean*) --
226+
Use Intel AES-NI hardware extensions (default: use if available).
227+
228+
:Return: an AES object, of the applicable mode.
229+
"""
230+
231+
kwargs["add_aes_modes"] = True
232+
return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs)
233+
234+
235+
MODE_ECB = 1
236+
MODE_CBC = 2
237+
MODE_CFB = 3
238+
MODE_OFB = 5
239+
MODE_CTR = 6
240+
MODE_OPENPGP = 7
241+
MODE_CCM = 8
242+
MODE_EAX = 9
243+
MODE_SIV = 10
244+
MODE_GCM = 11
245+
MODE_OCB = 12
246+
247+
# Size of a data block (in bytes)
248+
block_size = 16
249+
# Size of a key (in bytes)
250+
key_size = (16, 24, 32)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
from typing import Union, Tuple, Optional, Dict
2+
3+
from Cryptodome.Cipher._mode_ecb import EcbMode
4+
from Cryptodome.Cipher._mode_cbc import CbcMode
5+
from Cryptodome.Cipher._mode_cfb import CfbMode
6+
from Cryptodome.Cipher._mode_ofb import OfbMode
7+
from Cryptodome.Cipher._mode_ctr import CtrMode
8+
from Cryptodome.Cipher._mode_openpgp import OpenPgpMode
9+
from Cryptodome.Cipher._mode_ccm import CcmMode
10+
from Cryptodome.Cipher._mode_eax import EaxMode
11+
from Cryptodome.Cipher._mode_gcm import GcmMode
12+
from Cryptodome.Cipher._mode_siv import SivMode
13+
from Cryptodome.Cipher._mode_ocb import OcbMode
14+
15+
AESMode = int
16+
17+
MODE_ECB: AESMode
18+
MODE_CBC: AESMode
19+
MODE_CFB: AESMode
20+
MODE_OFB: AESMode
21+
MODE_CTR: AESMode
22+
MODE_OPENPGP: AESMode
23+
MODE_CCM: AESMode
24+
MODE_EAX: AESMode
25+
MODE_GCM: AESMode
26+
MODE_SIV: AESMode
27+
MODE_OCB: AESMode
28+
29+
Buffer = Union[bytes, bytearray, memoryview]
30+
31+
def new(key: Buffer,
32+
mode: AESMode,
33+
iv : Buffer = ...,
34+
IV : Buffer = ...,
35+
nonce : Buffer = ...,
36+
segment_size : int = ...,
37+
mac_len : int = ...,
38+
assoc_len : int = ...,
39+
initial_value : Union[int, Buffer] = ...,
40+
counter : Dict = ...,
41+
use_aesni : bool = ...) -> \
42+
Union[EcbMode, CbcMode, CfbMode, OfbMode, CtrMode,
43+
OpenPgpMode, CcmMode, EaxMode, GcmMode,
44+
SivMode, OcbMode]: ...
45+
46+
block_size: int
47+
key_size: Tuple[int, int, int]

0 commit comments

Comments
 (0)