hive-nectar 0.0.6__py3-none-any.whl → 0.0.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of hive-nectar might be problematic. Click here for more details.
- {hive_nectar-0.0.6.dist-info → hive_nectar-0.0.7.dist-info}/METADATA +5 -3
- {hive_nectar-0.0.6.dist-info → hive_nectar-0.0.7.dist-info}/RECORD +46 -47
- nectar/account.py +43 -47
- nectar/amount.py +6 -11
- nectar/block.py +8 -9
- nectar/blockchain.py +4 -5
- nectar/blockchaininstance.py +4 -4
- nectar/blockchainobject.py +5 -6
- nectar/blurt.py +3 -4
- nectar/cli.py +14 -14
- nectar/comment.py +10 -11
- nectar/community.py +4 -5
- nectar/conveyor.py +3 -4
- nectar/exceptions.py +30 -24
- nectar/hive.py +3 -4
- nectar/hivesigner.py +2 -2
- nectar/imageuploader.py +2 -3
- nectar/price.py +6 -13
- nectar/rc.py +1 -2
- nectar/steem.py +3 -4
- nectar/transactionbuilder.py +12 -3
- nectar/version.py +1 -1
- nectar/vote.py +8 -9
- nectar/wallet.py +1 -1
- nectarapi/exceptions.py +20 -14
- nectarapi/version.py +1 -1
- nectarbase/ledgertransactions.py +2 -3
- nectarbase/memo.py +9 -10
- nectarbase/objects.py +4 -5
- nectarbase/operations.py +3 -7
- nectarbase/version.py +1 -1
- nectargraphenebase/__init__.py +0 -1
- nectargraphenebase/account.py +16 -37
- nectargraphenebase/base58.py +5 -8
- nectargraphenebase/bip32.py +5 -11
- nectargraphenebase/bip38.py +6 -7
- nectargraphenebase/ecdsasig.py +32 -37
- nectargraphenebase/objects.py +6 -7
- nectargraphenebase/signedtransactions.py +10 -9
- nectargraphenebase/types.py +9 -19
- nectargraphenebase/unsignedtransactions.py +21 -28
- nectargraphenebase/version.py +1 -1
- nectarstorage/masterpassword.py +2 -3
- nectargraphenebase/py23.py +0 -38
- {hive_nectar-0.0.6.dist-info → hive_nectar-0.0.7.dist-info}/WHEEL +0 -0
- {hive_nectar-0.0.6.dist-info → hive_nectar-0.0.7.dist-info}/entry_points.txt +0 -0
- {hive_nectar-0.0.6.dist-info → hive_nectar-0.0.7.dist-info}/licenses/LICENSE.txt +0 -0
nectargraphenebase/account.py
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
import binascii
|
|
3
3
|
import bisect
|
|
4
|
-
import codecs
|
|
5
4
|
import hashlib
|
|
6
5
|
import itertools
|
|
7
6
|
import os
|
|
8
7
|
import re
|
|
9
|
-
import sys
|
|
10
8
|
import unicodedata
|
|
11
9
|
from binascii import hexlify, unhexlify
|
|
12
10
|
|
|
@@ -17,7 +15,6 @@ from .bip32 import BIP32Key, parse_path
|
|
|
17
15
|
from .dictionary import words as BrainKeyDictionary
|
|
18
16
|
from .dictionary import words_bip39 as MnemonicDictionary
|
|
19
17
|
from .prefix import Prefix
|
|
20
|
-
from .py23 import PY2, py23_bytes
|
|
21
18
|
|
|
22
19
|
PBKDF2_ROUNDS = 2048
|
|
23
20
|
|
|
@@ -55,7 +52,7 @@ class PasswordKey(Prefix):
|
|
|
55
52
|
else:
|
|
56
53
|
seed = self.account + self.role + self.password
|
|
57
54
|
seed = self.normalize(seed)
|
|
58
|
-
a =
|
|
55
|
+
a = bytes(seed, "utf8")
|
|
59
56
|
s = hashlib.sha256(a).digest()
|
|
60
57
|
return PrivateKey(hexlify(s).decode("ascii"), prefix=self.prefix)
|
|
61
58
|
|
|
@@ -121,13 +118,13 @@ class BrainKey(Prefix):
|
|
|
121
118
|
number
|
|
122
119
|
"""
|
|
123
120
|
encoded = "%s %d" % (self.brainkey, self.sequence)
|
|
124
|
-
a =
|
|
121
|
+
a = bytes(encoded, "ascii")
|
|
125
122
|
s = hashlib.sha256(hashlib.sha512(a).digest()).digest()
|
|
126
123
|
return PrivateKey(hexlify(s).decode("ascii"), prefix=self.prefix)
|
|
127
124
|
|
|
128
125
|
def get_blind_private(self):
|
|
129
126
|
"""Derive private key from the brain key (and no sequence number)"""
|
|
130
|
-
a =
|
|
127
|
+
a = bytes(self.brainkey, "ascii")
|
|
131
128
|
return PrivateKey(hashlib.sha256(a).hexdigest(), prefix=self.prefix)
|
|
132
129
|
|
|
133
130
|
def get_public(self):
|
|
@@ -149,12 +146,7 @@ class BrainKey(Prefix):
|
|
|
149
146
|
raise AssertionError()
|
|
150
147
|
for j in range(0, word_count):
|
|
151
148
|
urand = os.urandom(2)
|
|
152
|
-
|
|
153
|
-
urand = py23_bytes(urand, "ascii")
|
|
154
|
-
if PY2:
|
|
155
|
-
num = int(codecs.encode(urand[::-1], "hex"), 16)
|
|
156
|
-
else:
|
|
157
|
-
num = int.from_bytes(urand, byteorder="little")
|
|
149
|
+
num = int.from_bytes(urand, byteorder="little")
|
|
158
150
|
rndMult = num / 2**16 # returns float between 0..1 (inclusive)
|
|
159
151
|
wIdx = int(round(len(dict_lines) * rndMult))
|
|
160
152
|
brainkey[j] = dict_lines[wIdx]
|
|
@@ -180,7 +172,7 @@ class Mnemonic(object):
|
|
|
180
172
|
"""
|
|
181
173
|
if strength not in [128, 160, 192, 224, 256]:
|
|
182
174
|
raise ValueError(
|
|
183
|
-
"Strength should be one of the following [128, 160, 192, 224, 256], but it is not (%d)."
|
|
175
|
+
"Strength should be one of the following: [128, 160, 192, 224, 256], but it is not (%d)."
|
|
184
176
|
% strength
|
|
185
177
|
)
|
|
186
178
|
return self.to_mnemonic(os.urandom(strength // 8))
|
|
@@ -223,18 +215,11 @@ class Mnemonic(object):
|
|
|
223
215
|
entropy[ii] |= 1 << (7 - jj)
|
|
224
216
|
# Take the digest of the entropy.
|
|
225
217
|
hashBytes = hashlib.sha256(entropy).digest()
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
([ord(c) & (1 << (7 - i)) != 0 for i in range(8)] for c in hashBytes)
|
|
230
|
-
)
|
|
231
|
-
)
|
|
232
|
-
else:
|
|
233
|
-
hashBits = list(
|
|
234
|
-
itertools.chain.from_iterable(
|
|
235
|
-
([c & (1 << (7 - i)) != 0 for i in range(8)] for c in hashBytes)
|
|
236
|
-
)
|
|
218
|
+
hashBits = list(
|
|
219
|
+
itertools.chain.from_iterable(
|
|
220
|
+
([c & (1 << (7 - i)) != 0 for i in range(8)] for c in hashBytes)
|
|
237
221
|
)
|
|
222
|
+
)
|
|
238
223
|
# Check all the checksum bits.
|
|
239
224
|
for i in range(checksumLengthBits):
|
|
240
225
|
if concatBits[entropyLengthBits + i] != hashBits[i]:
|
|
@@ -308,13 +293,7 @@ class Mnemonic(object):
|
|
|
308
293
|
@classmethod
|
|
309
294
|
def normalize_string(cls, txt):
|
|
310
295
|
"""Normalizes strings"""
|
|
311
|
-
|
|
312
|
-
utxt = txt.decode("utf8")
|
|
313
|
-
elif isinstance(txt, unicode if sys.version < "3" else str): # noqa: F821
|
|
314
|
-
utxt = txt
|
|
315
|
-
else:
|
|
316
|
-
raise TypeError("String value expected")
|
|
317
|
-
|
|
296
|
+
utxt = txt.decode("utf8")
|
|
318
297
|
return unicodedata.normalize("NFKD", utxt)
|
|
319
298
|
|
|
320
299
|
@classmethod
|
|
@@ -535,7 +514,7 @@ class Address(Prefix):
|
|
|
535
514
|
|
|
536
515
|
def __bytes__(self):
|
|
537
516
|
"""Returns the raw content of the ``Base58CheckEncoded`` address"""
|
|
538
|
-
return
|
|
517
|
+
return bytes(self._address)
|
|
539
518
|
|
|
540
519
|
|
|
541
520
|
class GrapheneAddress(Address):
|
|
@@ -683,7 +662,7 @@ class PublicKey(Prefix):
|
|
|
683
662
|
|
|
684
663
|
def __bytes__(self):
|
|
685
664
|
"""Returns the raw public key (has length 33)"""
|
|
686
|
-
return
|
|
665
|
+
return bytes(self._pk)
|
|
687
666
|
|
|
688
667
|
def __lt__(self, other):
|
|
689
668
|
"""For sorting of public keys (due to graphene),
|
|
@@ -774,13 +753,13 @@ class PrivateKey(Prefix):
|
|
|
774
753
|
sequence number
|
|
775
754
|
"""
|
|
776
755
|
encoded = "%s %d" % (str(self), sequence)
|
|
777
|
-
a =
|
|
756
|
+
a = bytes(encoded, "ascii")
|
|
778
757
|
s = hashlib.sha256(hashlib.sha512(a).digest()).digest()
|
|
779
758
|
return PrivateKey(hexlify(s).decode("ascii"), prefix=self.pubkey.prefix)
|
|
780
759
|
|
|
781
760
|
def child(self, offset256):
|
|
782
761
|
"""Derive new private key from this key and a sha256 "offset" """
|
|
783
|
-
a =
|
|
762
|
+
a = bytes(self.pubkey) + offset256
|
|
784
763
|
s = hashlib.sha256(a).digest()
|
|
785
764
|
return self.derive_from_seed(s)
|
|
786
765
|
|
|
@@ -789,7 +768,7 @@ class PrivateKey(Prefix):
|
|
|
789
768
|
Here, the key itself serves as a `seed`, and `offset`
|
|
790
769
|
is expected to be a sha256 digest.
|
|
791
770
|
"""
|
|
792
|
-
seed = int(hexlify(
|
|
771
|
+
seed = int(hexlify(bytes(self)).decode("ascii"), 16)
|
|
793
772
|
z = int(hexlify(offset).decode("ascii"), 16)
|
|
794
773
|
order = ecdsa.SECP256k1.order
|
|
795
774
|
secexp = (seed + z) % order
|
|
@@ -816,7 +795,7 @@ class PrivateKey(Prefix):
|
|
|
816
795
|
|
|
817
796
|
def __bytes__(self):
|
|
818
797
|
"""Returns the raw private key"""
|
|
819
|
-
return
|
|
798
|
+
return bytes(self._wif)
|
|
820
799
|
|
|
821
800
|
|
|
822
801
|
class BitcoinAddress(Address):
|
nectargraphenebase/base58.py
CHANGED
|
@@ -5,7 +5,6 @@ import string
|
|
|
5
5
|
from binascii import hexlify, unhexlify
|
|
6
6
|
|
|
7
7
|
from .prefix import Prefix
|
|
8
|
-
from .py23 import integer_types, py23_bytes, py23_chr, string_types
|
|
9
8
|
|
|
10
9
|
log = logging.getLogger(__name__)
|
|
11
10
|
|
|
@@ -99,14 +98,12 @@ BASE58_ALPHABET = b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
|
|
99
98
|
|
|
100
99
|
|
|
101
100
|
def base58decode(base58_str):
|
|
102
|
-
base58_text =
|
|
101
|
+
base58_text = bytes(base58_str, "ascii")
|
|
103
102
|
n = 0
|
|
104
103
|
leading_zeroes_count = 0
|
|
105
104
|
for b in base58_text:
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
else:
|
|
109
|
-
n = n * 58 + BASE58_ALPHABET.find(b)
|
|
105
|
+
# b is always int in Python 3 when iterating bytes
|
|
106
|
+
n = n * 58 + BASE58_ALPHABET.find(bytes([b]))
|
|
110
107
|
if n == 0:
|
|
111
108
|
leading_zeroes_count += 1
|
|
112
109
|
res = bytearray()
|
|
@@ -120,7 +117,7 @@ def base58decode(base58_str):
|
|
|
120
117
|
|
|
121
118
|
|
|
122
119
|
def base58encode(hexstring):
|
|
123
|
-
byteseq =
|
|
120
|
+
byteseq = bytes(unhexlify(bytes(hexstring, "ascii")))
|
|
124
121
|
n = 0
|
|
125
122
|
leading_zeroes_count = 0
|
|
126
123
|
for c in byteseq:
|
|
@@ -156,7 +153,7 @@ def b58decode(v):
|
|
|
156
153
|
|
|
157
154
|
|
|
158
155
|
def base58CheckEncode(version, payload):
|
|
159
|
-
if isinstance(version,
|
|
156
|
+
if isinstance(version, str):
|
|
160
157
|
s = version + payload
|
|
161
158
|
else:
|
|
162
159
|
s = ("%.2x" % version) + payload
|
nectargraphenebase/bip32.py
CHANGED
|
@@ -17,7 +17,6 @@ from ecdsa.curves import SECP256k1
|
|
|
17
17
|
from ecdsa.numbertheory import square_root_mod_prime as sqrt_mod
|
|
18
18
|
|
|
19
19
|
from nectargraphenebase.base58 import base58CheckDecode, base58CheckEncode
|
|
20
|
-
from nectargraphenebase.py23 import py23_bytes
|
|
21
20
|
|
|
22
21
|
VerifyKey = ecdsa.VerifyingKey.from_public_point
|
|
23
22
|
SigningKey = ecdsa.SigningKey.from_string
|
|
@@ -45,7 +44,7 @@ EX_TEST_PUBLIC = [
|
|
|
45
44
|
|
|
46
45
|
|
|
47
46
|
def int_to_hex(x):
|
|
48
|
-
return
|
|
47
|
+
return bytes(hex(x)[2:], encoding="utf-8")
|
|
49
48
|
|
|
50
49
|
|
|
51
50
|
def parse_path(nstr, as_bytes=False):
|
|
@@ -123,11 +122,7 @@ class BIP32Key(object):
|
|
|
123
122
|
raise ValueError("unknown extended key version")
|
|
124
123
|
|
|
125
124
|
# Extract remaining fields
|
|
126
|
-
|
|
127
|
-
if type(raw[4]) == int:
|
|
128
|
-
depth = raw[4]
|
|
129
|
-
else:
|
|
130
|
-
depth = ord(raw[4])
|
|
125
|
+
depth = raw[4]
|
|
131
126
|
fpr = raw[5:9]
|
|
132
127
|
child = struct.unpack(">L", raw[9:13])[0]
|
|
133
128
|
chain = raw[13:45]
|
|
@@ -138,8 +133,7 @@ class BIP32Key(object):
|
|
|
138
133
|
secret = secret[1:]
|
|
139
134
|
else:
|
|
140
135
|
# Recover public curve point from compressed key
|
|
141
|
-
|
|
142
|
-
lsb = secret[0] & 1 if type(secret[0]) == int else ord(secret[0]) & 1
|
|
136
|
+
lsb = secret[0] & 1
|
|
143
137
|
x = int.from_bytes(secret[1:], "big")
|
|
144
138
|
ys = (x**3 + 7) % FIELD_ORDER # y^2 = x^3 + 7 mod p
|
|
145
139
|
y = sqrt_mod(ys, FIELD_ORDER)
|
|
@@ -167,10 +161,10 @@ class BIP32Key(object):
|
|
|
167
161
|
Create a public or private BIP32Key using key material and chain code.
|
|
168
162
|
|
|
169
163
|
secret This is the source material to generate the keypair, either a
|
|
170
|
-
32-byte
|
|
164
|
+
32-byte str representation of a private key, or the ECDSA
|
|
171
165
|
library object representing a public key.
|
|
172
166
|
|
|
173
|
-
chain This is a 32-byte
|
|
167
|
+
chain This is a 32-byte str representation of the chain code
|
|
174
168
|
|
|
175
169
|
depth Child depth; parent increments its own by one when assigning this
|
|
176
170
|
|
nectargraphenebase/bip38.py
CHANGED
|
@@ -6,7 +6,6 @@ from binascii import hexlify, unhexlify
|
|
|
6
6
|
|
|
7
7
|
from .account import PrivateKey
|
|
8
8
|
from .base58 import Base58, base58decode
|
|
9
|
-
from .py23 import py23_bytes, text_type
|
|
10
9
|
|
|
11
10
|
log = logging.getLogger(__name__)
|
|
12
11
|
|
|
@@ -62,16 +61,16 @@ def encrypt(privkey, passphrase):
|
|
|
62
61
|
|
|
63
62
|
privkeyhex = repr(privkey) # hex
|
|
64
63
|
addr = format(privkey.bitcoin.address, "BTC")
|
|
65
|
-
a =
|
|
64
|
+
a = bytes(addr, "ascii")
|
|
66
65
|
salt = hashlib.sha256(hashlib.sha256(a).digest()).digest()[0:4]
|
|
67
66
|
if sys.version < "3":
|
|
68
|
-
if isinstance(passphrase,
|
|
67
|
+
if isinstance(passphrase, str):
|
|
69
68
|
passphrase = passphrase.encode("utf-8")
|
|
70
69
|
|
|
71
70
|
if SCRYPT_MODULE == "scrypt":
|
|
72
71
|
key = scrypt.hash(passphrase, salt, 16384, 8, 8)
|
|
73
72
|
elif SCRYPT_MODULE == "pylibscrypt":
|
|
74
|
-
key = scrypt.scrypt(
|
|
73
|
+
key = scrypt.scrypt(bytes(passphrase, "utf-8"), salt, 16384, 8, 8)
|
|
75
74
|
else:
|
|
76
75
|
raise ValueError("No scrypt module loaded")
|
|
77
76
|
(derived_half1, derived_half2) = (key[:32], key[32:])
|
|
@@ -106,12 +105,12 @@ def decrypt(encrypted_privkey, passphrase):
|
|
|
106
105
|
salt = d[0:4]
|
|
107
106
|
d = d[4:-4]
|
|
108
107
|
if sys.version < "3":
|
|
109
|
-
if isinstance(passphrase,
|
|
108
|
+
if isinstance(passphrase, str):
|
|
110
109
|
passphrase = passphrase.encode("utf-8")
|
|
111
110
|
if SCRYPT_MODULE == "scrypt":
|
|
112
111
|
key = scrypt.hash(passphrase, salt, 16384, 8, 8)
|
|
113
112
|
elif SCRYPT_MODULE == "pylibscrypt":
|
|
114
|
-
key = scrypt.scrypt(
|
|
113
|
+
key = scrypt.scrypt(bytes(passphrase, "utf-8"), salt, 16384, 8, 8)
|
|
115
114
|
else:
|
|
116
115
|
raise ValueError("No scrypt module loaded")
|
|
117
116
|
derivedhalf1 = key[0:32]
|
|
@@ -127,7 +126,7 @@ def decrypt(encrypted_privkey, passphrase):
|
|
|
127
126
|
""" Verify Salt """
|
|
128
127
|
privkey = PrivateKey(format(wif, "wif"))
|
|
129
128
|
addr = format(privkey.bitcoin.address, "BTC")
|
|
130
|
-
a =
|
|
129
|
+
a = bytes(addr, "ascii")
|
|
131
130
|
saltverify = hashlib.sha256(hashlib.sha256(a).digest()).digest()[0:4]
|
|
132
131
|
if saltverify != salt:
|
|
133
132
|
raise SaltException("checksum verification failed! Password may be incorrect.")
|
nectargraphenebase/ecdsasig.py
CHANGED
|
@@ -8,7 +8,6 @@ from binascii import hexlify
|
|
|
8
8
|
import ecdsa
|
|
9
9
|
|
|
10
10
|
from .account import PrivateKey, PublicKey
|
|
11
|
-
from .py23 import bytes_types, py23_bytes
|
|
12
11
|
|
|
13
12
|
log = logging.getLogger(__name__)
|
|
14
13
|
|
|
@@ -22,7 +21,7 @@ if not SECP256K1_MODULE:
|
|
|
22
21
|
|
|
23
22
|
SECP256K1_MODULE = "secp256k1"
|
|
24
23
|
SECP256K1_AVAILABLE = True
|
|
25
|
-
except:
|
|
24
|
+
except Exception:
|
|
26
25
|
try:
|
|
27
26
|
import secp256k1
|
|
28
27
|
|
|
@@ -31,26 +30,22 @@ if not SECP256K1_MODULE:
|
|
|
31
30
|
except ImportError:
|
|
32
31
|
try:
|
|
33
32
|
import cryptography
|
|
34
|
-
|
|
35
|
-
SECP256K1_MODULE = "cryptography"
|
|
36
|
-
CRYPTOGRAPHY_AVAILABLE = True
|
|
37
33
|
except ImportError:
|
|
38
34
|
SECP256K1_MODULE = "ecdsa"
|
|
35
|
+
else:
|
|
36
|
+
SECP256K1_MODULE = "cryptography"
|
|
37
|
+
CRYPTOGRAPHY_AVAILABLE = True
|
|
39
38
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
CRYPTOGRAPHY_AVAILABLE = True
|
|
51
|
-
except ImportError:
|
|
52
|
-
CRYPTOGRAPHY_AVAILABLE = False
|
|
53
|
-
log.debug("Cryptography not available")
|
|
39
|
+
try:
|
|
40
|
+
from cryptography.hazmat.backends import default_backend
|
|
41
|
+
from cryptography.hazmat.primitives import hashes
|
|
42
|
+
from cryptography.hazmat.primitives.asymmetric import ec
|
|
43
|
+
from cryptography.hazmat.primitives.asymmetric.utils import (
|
|
44
|
+
decode_dss_signature,
|
|
45
|
+
encode_dss_signature,
|
|
46
|
+
)
|
|
47
|
+
except ImportError:
|
|
48
|
+
pass
|
|
54
49
|
|
|
55
50
|
log.debug("Using SECP256K1 module: %s" % SECP256K1_MODULE)
|
|
56
51
|
|
|
@@ -76,7 +71,7 @@ def compressedPubkey(pk):
|
|
|
76
71
|
x = p.x()
|
|
77
72
|
y = p.y()
|
|
78
73
|
x_str = ecdsa.util.number_to_string(x, order)
|
|
79
|
-
return
|
|
74
|
+
return bytes(chr(2 + (y & 1)), "ascii") + x_str
|
|
80
75
|
|
|
81
76
|
|
|
82
77
|
def recover_public_key(digest, signature, i, message=None):
|
|
@@ -103,20 +98,20 @@ def recover_public_key(digest, signature, i, message=None):
|
|
|
103
98
|
Q = ecdsa.numbertheory.inverse_mod(r, order) * (s * R + (-e % order) * G)
|
|
104
99
|
|
|
105
100
|
if SECP256K1_MODULE == "cryptography" and message is not None:
|
|
106
|
-
if not isinstance(message,
|
|
107
|
-
message =
|
|
101
|
+
if not isinstance(message, bytes):
|
|
102
|
+
message = bytes(message, "utf-8")
|
|
108
103
|
sigder = encode_dss_signature(r, s)
|
|
109
104
|
try:
|
|
110
105
|
Q_point = Q.to_affine()
|
|
111
106
|
public_key = ec.EllipticCurvePublicNumbers(
|
|
112
107
|
Q_point.x(), Q_point.y(), ec.SECP256K1()
|
|
113
108
|
).public_key(default_backend())
|
|
114
|
-
except:
|
|
109
|
+
except Exception:
|
|
115
110
|
try:
|
|
116
111
|
public_key = ec.EllipticCurvePublicNumbers(
|
|
117
112
|
Q._Point__x, Q._Point__y, ec.SECP256K1()
|
|
118
113
|
).public_key(default_backend())
|
|
119
|
-
except:
|
|
114
|
+
except Exception:
|
|
120
115
|
Q_point = Q.to_affine()
|
|
121
116
|
public_key = ec.EllipticCurvePublicNumbers(
|
|
122
117
|
int(Q_point.x()), int(Q_point.y()), ec.SECP256K1()
|
|
@@ -136,8 +131,8 @@ def recoverPubkeyParameter(message, digest, signature, pubkey):
|
|
|
136
131
|
"""Use to derive a number that allows to easily recover the
|
|
137
132
|
public key from the signature
|
|
138
133
|
"""
|
|
139
|
-
if not isinstance(message,
|
|
140
|
-
message =
|
|
134
|
+
if not isinstance(message, bytes):
|
|
135
|
+
message = bytes(message, "utf-8")
|
|
141
136
|
for i in range(0, 4):
|
|
142
137
|
if SECP256K1_MODULE == "secp256k1":
|
|
143
138
|
sig = pubkey.ecdsa_recoverable_deserialize(signature, i)
|
|
@@ -155,7 +150,7 @@ def recoverPubkeyParameter(message, digest, signature, pubkey):
|
|
|
155
150
|
p_comp = hexlify(compressedPubkey(p))
|
|
156
151
|
p_string = hexlify(p.to_string())
|
|
157
152
|
if isinstance(pubkey, PublicKey):
|
|
158
|
-
pubkey_string =
|
|
153
|
+
pubkey_string = bytes(repr(pubkey), "latin")
|
|
159
154
|
else: # pragma: no cover
|
|
160
155
|
pubkey_string = hexlify(pubkey.to_string())
|
|
161
156
|
if p_string == pubkey_string or p_comp == pubkey_string:
|
|
@@ -169,13 +164,13 @@ def sign_message(message, wif, hashfn=hashlib.sha256):
|
|
|
169
164
|
:param str wif: Private key in
|
|
170
165
|
"""
|
|
171
166
|
|
|
172
|
-
if not isinstance(message,
|
|
173
|
-
message =
|
|
167
|
+
if not isinstance(message, bytes):
|
|
168
|
+
message = bytes(message, "utf-8")
|
|
174
169
|
|
|
175
170
|
digest = hashfn(message).digest()
|
|
176
171
|
priv_key = PrivateKey(wif)
|
|
177
172
|
if SECP256K1_MODULE == "secp256k1":
|
|
178
|
-
p =
|
|
173
|
+
p = bytes(priv_key)
|
|
179
174
|
ndata = secp256k1.ffi.new("const int *ndata")
|
|
180
175
|
ndata[0] = 0
|
|
181
176
|
while True:
|
|
@@ -220,7 +215,7 @@ def sign_message(message, wif, hashfn=hashlib.sha256):
|
|
|
220
215
|
break
|
|
221
216
|
else: # pragma: no branch # pragma: no cover
|
|
222
217
|
cnt = 0
|
|
223
|
-
p =
|
|
218
|
+
p = bytes(priv_key)
|
|
224
219
|
sk = ecdsa.SigningKey.from_string(p, curve=ecdsa.SECP256k1)
|
|
225
220
|
while 1:
|
|
226
221
|
cnt += 1
|
|
@@ -270,13 +265,13 @@ def sign_message(message, wif, hashfn=hashlib.sha256):
|
|
|
270
265
|
|
|
271
266
|
|
|
272
267
|
def verify_message(message, signature, hashfn=hashlib.sha256, recover_parameter=None):
|
|
273
|
-
if not isinstance(message,
|
|
274
|
-
message =
|
|
275
|
-
if not isinstance(signature,
|
|
276
|
-
signature =
|
|
277
|
-
if not isinstance(message,
|
|
268
|
+
if not isinstance(message, bytes):
|
|
269
|
+
message = bytes(message, "utf-8")
|
|
270
|
+
if not isinstance(signature, bytes):
|
|
271
|
+
signature = bytes(signature, "utf-8")
|
|
272
|
+
if not isinstance(message, bytes):
|
|
278
273
|
raise AssertionError()
|
|
279
|
-
if not isinstance(signature,
|
|
274
|
+
if not isinstance(signature, bytes):
|
|
280
275
|
raise AssertionError()
|
|
281
276
|
digest = hashfn(message).digest()
|
|
282
277
|
sig = signature[1:]
|
nectargraphenebase/objects.py
CHANGED
|
@@ -4,13 +4,12 @@ import json
|
|
|
4
4
|
from nectargraphenebase.types import Id, JsonObj, Optional, String
|
|
5
5
|
|
|
6
6
|
from .operationids import operations
|
|
7
|
-
from .py23 import integer_types, py23_bytes, string_types
|
|
8
7
|
|
|
9
8
|
|
|
10
9
|
class Operation(object):
|
|
11
10
|
def __init__(self, op):
|
|
12
11
|
if isinstance(op, list) and len(op) == 2:
|
|
13
|
-
if isinstance(op[0],
|
|
12
|
+
if isinstance(op[0], int):
|
|
14
13
|
self.opId = op[0]
|
|
15
14
|
name = self.getOperationNameForId(self.opId)
|
|
16
15
|
else:
|
|
@@ -61,7 +60,7 @@ class Operation(object):
|
|
|
61
60
|
return class_
|
|
62
61
|
|
|
63
62
|
def __bytes__(self):
|
|
64
|
-
return
|
|
63
|
+
return bytes(Id(self.opId)) + bytes(self.op)
|
|
65
64
|
|
|
66
65
|
def __str__(self):
|
|
67
66
|
return json.dumps([self.opId, self.op.toJson()])
|
|
@@ -83,13 +82,13 @@ class GrapheneObject(object):
|
|
|
83
82
|
|
|
84
83
|
def __bytes__(self):
|
|
85
84
|
if self.data is None:
|
|
86
|
-
return
|
|
85
|
+
return bytes()
|
|
87
86
|
b = b""
|
|
88
87
|
for name, value in list(self.data.items()):
|
|
89
|
-
if isinstance(value,
|
|
90
|
-
b +=
|
|
88
|
+
if isinstance(value, str):
|
|
89
|
+
b += bytes(value, "utf-8")
|
|
91
90
|
else:
|
|
92
|
-
b +=
|
|
91
|
+
b += bytes(value)
|
|
93
92
|
return b
|
|
94
93
|
|
|
95
94
|
def __json__(self):
|
|
@@ -6,8 +6,6 @@ from collections import OrderedDict
|
|
|
6
6
|
|
|
7
7
|
import ecdsa
|
|
8
8
|
|
|
9
|
-
from nectargraphenebase.py23 import py23_bytes
|
|
10
|
-
|
|
11
9
|
from .account import PublicKey
|
|
12
10
|
from .chains import known_chains
|
|
13
11
|
from .ecdsasig import sign_message, verify_message
|
|
@@ -48,9 +46,12 @@ class Signed_Transaction(GrapheneObject):
|
|
|
48
46
|
if "signatures" not in kwargs:
|
|
49
47
|
kwargs["signatures"] = Array([])
|
|
50
48
|
else:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
)
|
|
49
|
+
# Defensive: if a string, wrap in a list and log warning
|
|
50
|
+
sigs = kwargs["signatures"]
|
|
51
|
+
if isinstance(sigs, str):
|
|
52
|
+
log.warning("signatures was a string, converting to list to avoid type errors.")
|
|
53
|
+
sigs = [sigs]
|
|
54
|
+
kwargs["signatures"] = Array([Signature(unhexlify(a)) for a in sigs])
|
|
54
55
|
|
|
55
56
|
if "operations" in kwargs:
|
|
56
57
|
opklass = self.getOperationKlass()
|
|
@@ -83,7 +84,7 @@ class Signed_Transaction(GrapheneObject):
|
|
|
83
84
|
self.data.pop("signatures", None)
|
|
84
85
|
|
|
85
86
|
# Generage Hash of the seriliazed version
|
|
86
|
-
h = hashlib.sha256(
|
|
87
|
+
h = hashlib.sha256(bytes(self)).digest()
|
|
87
88
|
|
|
88
89
|
# recover signatures
|
|
89
90
|
self.data["signatures"] = sigs
|
|
@@ -133,7 +134,7 @@ class Signed_Transaction(GrapheneObject):
|
|
|
133
134
|
# Get message to sign
|
|
134
135
|
# bytes(self) will give the wire formated data according to
|
|
135
136
|
# GrapheneObject and the data given in __init__()
|
|
136
|
-
self.message = unhexlify(self.chainid) +
|
|
137
|
+
self.message = unhexlify(self.chainid) + bytes(self)
|
|
137
138
|
self.digest = hashlib.sha256(self.message).digest()
|
|
138
139
|
|
|
139
140
|
# restore signatures
|
|
@@ -150,13 +151,13 @@ class Signed_Transaction(GrapheneObject):
|
|
|
150
151
|
|
|
151
152
|
for signature in signatures:
|
|
152
153
|
if recover_parameter:
|
|
153
|
-
p = verify_message(self.message,
|
|
154
|
+
p = verify_message(self.message, bytes(signature))
|
|
154
155
|
else:
|
|
155
156
|
p = None
|
|
156
157
|
if p is None:
|
|
157
158
|
for i in range(4):
|
|
158
159
|
try:
|
|
159
|
-
p = verify_message(self.message,
|
|
160
|
+
p = verify_message(self.message, bytes(signature), recover_parameter=i)
|
|
160
161
|
phex = hexlify(p).decode("ascii")
|
|
161
162
|
pubKeysFound.append(phex)
|
|
162
163
|
except Exception:
|
nectargraphenebase/types.py
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
import json
|
|
3
3
|
import struct
|
|
4
|
-
import sys
|
|
5
4
|
import time
|
|
6
5
|
from binascii import hexlify, unhexlify
|
|
7
6
|
from calendar import timegm
|
|
8
7
|
from datetime import datetime
|
|
9
8
|
|
|
10
|
-
from .py23 import py23_bytes
|
|
11
|
-
|
|
12
9
|
timeformat = "%Y-%m-%dT%H:%M:%S%Z"
|
|
13
10
|
|
|
14
11
|
|
|
@@ -247,7 +244,7 @@ class Array(object):
|
|
|
247
244
|
|
|
248
245
|
def __bytes__(self):
|
|
249
246
|
"""Returns bytes representation."""
|
|
250
|
-
return
|
|
247
|
+
return bytes(self.length) + b"".join([bytes(a) for a in self.data])
|
|
251
248
|
|
|
252
249
|
def __str__(self):
|
|
253
250
|
"""Returns data as string."""
|
|
@@ -271,10 +268,8 @@ class PointInTime(object):
|
|
|
271
268
|
"""Returns bytes representation."""
|
|
272
269
|
if isinstance(self.data, datetime):
|
|
273
270
|
unixtime = timegm(self.data.timetuple())
|
|
274
|
-
elif sys.version > "3":
|
|
275
|
-
unixtime = timegm(time.strptime((self.data + "UTC"), timeformat))
|
|
276
271
|
else:
|
|
277
|
-
unixtime = timegm(time.strptime((self.data + "UTC"), timeformat
|
|
272
|
+
unixtime = timegm(time.strptime((self.data + "UTC"), timeformat))
|
|
278
273
|
if unixtime < 0:
|
|
279
274
|
return struct.pack("<i", unixtime)
|
|
280
275
|
return struct.pack("<I", unixtime)
|
|
@@ -331,22 +326,17 @@ class Optional(object):
|
|
|
331
326
|
def __bytes__(self):
|
|
332
327
|
"""Returns data as bytes."""
|
|
333
328
|
if not self.data:
|
|
334
|
-
return
|
|
329
|
+
return bytes(Bool(0))
|
|
335
330
|
else:
|
|
336
|
-
return (
|
|
337
|
-
py23_bytes(Bool(1)) + py23_bytes(self.data)
|
|
338
|
-
if py23_bytes(self.data)
|
|
339
|
-
else py23_bytes(Bool(0))
|
|
340
|
-
)
|
|
331
|
+
return bytes(Bool(1)) + bytes(self.data)
|
|
341
332
|
|
|
342
333
|
def __str__(self):
|
|
343
334
|
"""Returns data as string."""
|
|
344
335
|
return str(self.data)
|
|
345
336
|
|
|
346
337
|
def isempty(self):
|
|
347
|
-
if
|
|
348
|
-
|
|
349
|
-
return not bool(py23_bytes(self.data))
|
|
338
|
+
"""Returns True if data is empty, False otherwise."""
|
|
339
|
+
return not self.data
|
|
350
340
|
|
|
351
341
|
|
|
352
342
|
class Static_variant(object):
|
|
@@ -359,7 +349,7 @@ class Static_variant(object):
|
|
|
359
349
|
|
|
360
350
|
def __bytes__(self):
|
|
361
351
|
"""Returns bytes representation."""
|
|
362
|
-
return varint(self.type_id) +
|
|
352
|
+
return varint(self.type_id) + bytes(self.data)
|
|
363
353
|
|
|
364
354
|
def __str__(self):
|
|
365
355
|
"""Returns data as string."""
|
|
@@ -378,7 +368,7 @@ class Map(object):
|
|
|
378
368
|
b = b""
|
|
379
369
|
b += varint(len(self.data))
|
|
380
370
|
for e in self.data:
|
|
381
|
-
b +=
|
|
371
|
+
b += bytes(e[0]) + bytes(e[1])
|
|
382
372
|
return b
|
|
383
373
|
|
|
384
374
|
def __str__(self):
|
|
@@ -395,7 +385,7 @@ class Id(object):
|
|
|
395
385
|
|
|
396
386
|
def __bytes__(self):
|
|
397
387
|
"""Returns bytes representation."""
|
|
398
|
-
return
|
|
388
|
+
return bytes(self.data)
|
|
399
389
|
|
|
400
390
|
def __str__(self):
|
|
401
391
|
"""Returns data as string."""
|