-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathmessage.py
More file actions
128 lines (96 loc) · 3.58 KB
/
message.py
File metadata and controls
128 lines (96 loc) · 3.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import json
from binascii import unhexlify
from typing import Union
from Cryptodome.Hash import keccak
from coincurve import PublicKey
from crypto.identity.private_key import PrivateKey
class Message(object):
public_key: bytes
message: bytes
signature: bytes
def __init__(self, public_key: Union[bytes, str], message: Union[bytes, str], signature: Union[bytes, str]):
if isinstance(public_key, str):
self.public_key = public_key.encode()
else:
self.public_key = public_key
if isinstance(message, str):
self.message = message.encode()
else:
self.message = message
if isinstance(signature, str):
self.signature = signature.encode()
else:
self.signature = signature
@staticmethod
def new(public_key: Union[bytes, str], message: Union[bytes, str], signature: Union[bytes, str]):
"""Creates a new message object
Returns:
Message: returns a message object
"""
return Message(
public_key=public_key,
message=message,
signature=signature,
)
@classmethod
def sign(cls, message: Union[bytes, str], passphrase: Union[bytes, str]):
"""Signs a message
Args:
message (str/bytes): a message you wish to sign
passphrase (str/byes): passphrase you wish to use to sign the message
Returns:
Message: returns a message object
"""
if isinstance(message, str):
message = message.encode()
if not isinstance(passphrase, str):
passphrase = passphrase.hex()
private_key = PrivateKey.from_passphrase(passphrase)
public_key = private_key.public_key
transaction_signature = private_key.sign(message)
signature_v = bytes([transaction_signature[0]]).hex()
signature_r = transaction_signature[1:33].hex()
signature_s = transaction_signature[33:].hex()
signature = signature_r + signature_s + signature_v
return cls(
message=message,
signature=signature,
public_key=public_key,
)
def verify(self):
"""Verify the Message object
Returns:
bool: returns a boolean - true if verified, false if not
"""
signature = unhexlify(self.signature)
message_hash = keccak.new(data=self.message, digest_bits=256).digest()
signature_r = signature[0:32]
signature_s = signature[32:64]
signature_v = signature[64]
signature = signature_r + signature_s + bytes([signature_v - 27])
public_key = PublicKey.from_signature_and_message(signature, message_hash, hasher=None)
return public_key.format() == unhexlify(self.public_key)
def to_dict(self):
"""Return a dictionary of the message
Returns:
dict: dictionary consiting of public_key, signature and message
"""
data = {
'public_key': self.public_key.decode(),
'signature': self.signature.decode(),
'message': self.message.decode(),
}
return data
def to_json(self):
"""Returns a json string of the the message
Returns:
str: json string consisting of public_key, signature and message
"""
data = self.to_dict()
return json.dumps(data)
def __str__(self):
"""Returns a string representation of the message
Returns:
str: string representation of the message
"""
return self.to_json()