Skip to content

Commit 59151c1

Browse files
committed
Created private and public key step by step
1 parent fc1d749 commit 59151c1

File tree

10 files changed

+748
-1
lines changed

10 files changed

+748
-1
lines changed

Blockchain/Backend/core/EllepticCurve/EllepticCurve.py

+400
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
"""
2+
Copyright (c) 2021 Codiesalert.com
3+
These scripts shouldn't be used for commercial purpose without Codies Alert Permission
4+
Any violations may lead to legal action
5+
"""
6+
7+
8+
class FieldElement:
9+
def __init__(self, num, prime):
10+
if num >= prime or num < 0:
11+
error = "Num {} not in field range 0 to {}".format(num, prime - 1)
12+
raise ValueError(error)
13+
self.num = num
14+
self.prime = prime
15+
16+
def __repr__(self):
17+
return "FieldElement_{}({})".format(self.prime, self.num)
18+
19+
def __eq__(self, other):
20+
if other is None:
21+
return False
22+
return self.num == other.num and self.prime == other.prime
23+
24+
def __ne__(self, other):
25+
# this should be the inverse of the == operator
26+
return not (self == other)
27+
28+
def __add__(self, other):
29+
if self.prime != other.prime:
30+
raise TypeError("Cannot add two numbers in different Fields")
31+
# self.num and other.num are the actual values
32+
# self.prime is what we need to mod against
33+
num = (self.num + other.num) % self.prime
34+
# We return an element of the same class
35+
return self.__class__(num, self.prime)
36+
37+
def __sub__(self, other):
38+
if self.prime != other.prime:
39+
raise TypeError("Cannot subtract two numbers in different Fields")
40+
# self.num and other.num are the actual values
41+
# self.prime is what we need to mod against
42+
num = (self.num - other.num) % self.prime
43+
# We return an element of the same class
44+
return self.__class__(num, self.prime)
45+
46+
def __mul__(self, other):
47+
if self.prime != other.prime:
48+
raise TypeError("Cannot multiply two numbers in different Fields")
49+
# self.num and other.num are the actual values
50+
# self.prime is what we need to mod against
51+
num = (self.num * other.num) % self.prime
52+
# We return an element of the same class
53+
return self.__class__(num, self.prime)
54+
55+
def __pow__(self, exponent):
56+
n = exponent % (self.prime - 1)
57+
num = pow(self.num, n, self.prime)
58+
return self.__class__(num, self.prime)
59+
60+
def __truediv__(self, other):
61+
if self.prime != other.prime:
62+
raise TypeError("Cannot divide two numbers in different Fields")
63+
# self.num and other.num are the actual values
64+
# self.prime is what we need to mod against
65+
# use fermat's little theorem:
66+
# self.num**(p-1) % p == 1
67+
# this means:
68+
# 1/n == pow(n, p-2, p)
69+
num = (self.num * pow(other.num, self.prime - 2, self.prime)) % self.prime
70+
# We return an element of the same class
71+
return self.__class__(num, self.prime)
72+
73+
def __rmul__(self, coefficient):
74+
num = (self.num * coefficient) % self.prime
75+
return self.__class__(num=num, prime=self.prime)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
"""
2+
Copyright (c) 2021 Codiesalert.com
3+
These scripts should be used for commercial purpose without Codies Alert Permission
4+
Any violations may lead to legal action
5+
"""
6+
from FieldElement import FieldElement
7+
8+
9+
class Point:
10+
def __init__(self, x, y, a, b):
11+
self.a = a
12+
self.b = b
13+
self.x = x
14+
self.y = y
15+
if self.x is None and self.y is None:
16+
return
17+
if self.y ** 2 != self.x ** 3 + a * x + b:
18+
raise ValueError("({}, {}) is not on the curve".format(x, y))
19+
20+
# end::source1[]
21+
22+
def __eq__(self, other):
23+
return (
24+
self.x == other.x
25+
and self.y == other.y
26+
and self.a == other.a
27+
and self.b == other.b
28+
)
29+
30+
def __ne__(self, other):
31+
# this should be the inverse of the == operator
32+
return not (self == other)
33+
34+
def __repr__(self):
35+
if self.x is None:
36+
return "Point(infinity)"
37+
elif isinstance(self.x, FieldElement):
38+
return "Point({},{})_{}_{} FieldElement({})".format(
39+
self.x.num, self.y.num, self.a.num, self.b.num, self.x.prime
40+
)
41+
else:
42+
return "Point({},{})_{}_{}".format(self.x, self.y, self.a, self.b)
43+
44+
def __add__(self, other):
45+
if self.a != other.a or self.b != other.b:
46+
raise TypeError(
47+
"Points {}, {} are not on the same curve".format(self, other)
48+
)
49+
# Case 0.0: self is the point at infinity, return other
50+
if self.x is None:
51+
return other
52+
# Case 0.1: other is the point at infinity, return self
53+
if other.x is None:
54+
return self
55+
56+
# Case 1: self.x == other.x, self.y != other.y
57+
# Result is point at infinity
58+
if self.x == other.x and self.y != other.y:
59+
return self.__class__(None, None, self.a, self.b)
60+
61+
# Case 2: self.x ≠ other.x
62+
# Formula (x3,y3)==(x1,y1)+(x2,y2)
63+
# s=(y2-y1)/(x2-x1)
64+
# x3=s**2-x1-x2
65+
# y3=s*(x1-x3)-y1
66+
if self.x != other.x:
67+
s = (other.y - self.y) / (other.x - self.x)
68+
x = s ** 2 - self.x - other.x
69+
y = s * (self.x - x) - self.y
70+
return self.__class__(x, y, self.a, self.b)
71+
72+
# Case 4: if we are tangent to the vertical line,
73+
# we return the point at infinity
74+
# note instead of figuring out what 0 is for each type
75+
# we just use 0 * self.x
76+
if self == other and self.y == 0 * self.x:
77+
return self.__class__(None, None, self.a, self.b)
78+
79+
# Case 3: self == other
80+
# Formula (x3,y3)=(x1,y1)+(x1,y1)
81+
# s=(3*x1**2+a)/(2*y1)
82+
# x3=s**2-2*x1
83+
# y3=s*(x1-x3)-y1
84+
if self == other:
85+
s = (3 * self.x ** 2 + self.a) / (2 * self.y)
86+
x = s ** 2 - 2 * self.x
87+
y = s * (self.x - x) - self.y
88+
return self.__class__(x, y, self.a, self.b)
89+
90+
# tag::source3[]
91+
def __rmul__(self, coefficient):
92+
coef = coefficient
93+
current = self # <1>
94+
result = self.__class__(None, None, self.a, self.b) # <2>
95+
while coef:
96+
if coef & 1: # <3>
97+
result += current
98+
current += current # <4>
99+
coef >>= 1 # <5>
100+
return result
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
"""
2+
Copyright (c) 2021 Codiesalert.com
3+
These scripts should be used for commercial purpose without Codies Alert Permission
4+
Any violations may lead to legal action
5+
"""
6+
from FieldElement import FieldElement
7+
from Point import Point
8+
9+
P = 2 ** 256 - 2 ** 32 - 977
10+
11+
12+
class Sha256Field(FieldElement):
13+
def __init__(self, num, prime=None):
14+
super().__init__(num=num, prime=P)
15+
16+
def __repr__(self):
17+
return "{:x}".format(self.num).zfill(64)

Blockchain/Backend/core/EllepticCurve/__init__.py.txt

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
"""
2+
Copyright (c) 2021 Codiesalert.com
3+
These scripts shouldn't be used for commercial purpose without Codies Alert Permission
4+
Any violations may lead to legal action
5+
"""
6+
from Blockchain.Backend.util.util import hash160
7+
from Blockchain.Backend.core.EllepticCurve.EllepticCurve import Sha256Point, Signature
8+
9+
10+
def op_dup(stack):
11+
12+
if len(stack) < 1:
13+
return False
14+
stack.append(stack[-1])
15+
16+
return True
17+
18+
19+
def op_hash160(stack):
20+
if len(stack) < 1:
21+
return False
22+
element = stack.pop()
23+
h160 = hash160(element)
24+
stack.append(h160)
25+
return True
26+
27+
28+
def op_equal(stack):
29+
if len(stack) < 2:
30+
return False
31+
32+
element1 = stack.pop()
33+
element2 = stack.pop()
34+
35+
if element1 == element2:
36+
stack.append(1)
37+
else:
38+
stack.append(0)
39+
40+
return True
41+
42+
43+
def op_verify(stack):
44+
if len(stack) < 1:
45+
False
46+
element = stack.pop()
47+
48+
if element == 0:
49+
return False
50+
51+
return True
52+
53+
54+
def op_equalverify(stack):
55+
return op_equal(stack) and op_verify(stack)
56+
57+
58+
def op_checksig(stack, z):
59+
if len(stack) < 1:
60+
return False
61+
62+
sec_pubkey = stack.pop()
63+
der_signature = stack.pop()[:-1]
64+
65+
try:
66+
point = Sha256Point.parse(sec_pubkey)
67+
sig = Signature.parse(der_signature)
68+
except Exception as e:
69+
return False
70+
71+
if point.verify(z, sig):
72+
stack.append(1)
73+
return True
74+
else:
75+
stack.append(0)
76+
return False
77+
78+
79+
OP_CODE_FUNCTION = {118: op_dup, 136: op_equalverify, 169: op_hash160, 172: op_checksig}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from FieldElement import FieldElement
2+
from Point import Point
3+
a = FieldElement(num = 0, prime = 223)
4+
b = FieldElement(num = 7, prime = 223)
5+
x = FieldElement(num = 192, prime = 223)
6+
y = FieldElement(num = 105, prime = 223)
7+
8+
p1 = Point(x, y, a, b)
9+
print(p1)

Blockchain/Backend/util/util.py

+6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import hashlib
2+
from Crypto.Hash import RIPEMD160
3+
from hashlib import sha256
24

35

46
def hash256(s):
57
"""Two rounds of SHA256"""
68
return hashlib.sha256(hashlib.sha256(s).digest()).digest()
9+
10+
11+
def hash160(s):
12+
return RIPEMD160.new(sha256(s).digest()).digest()

Blockchain/Client/account.py

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import sys
2+
import secrets
3+
4+
sys.path.append('D:/xampp/htdocs/sand_box/get_job/custom-python-blockchain')
5+
from Blockchain.Backend.core.EllepticCurve.EllepticCurve import Sha256Point
6+
from Blockchain.Backend.util.util import hash160, hash256
7+
8+
9+
class Account:
10+
def createKeys(self):
11+
"""Secp256k1 Curve Generator Points"""
12+
Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
13+
Gy = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
14+
15+
G = Sha256Point(Gx, Gy)
16+
17+
privateKey = secrets.randbits(256)
18+
19+
unCompressedPublicKey = privateKey * G
20+
xpoint = unCompressedPublicKey.x
21+
ypoint = unCompressedPublicKey.y
22+
23+
if ypoint.num % 2 == 0:
24+
compressesKey = b"\x02" + xpoint.num.to_bytes(32, "big")
25+
else:
26+
compressesKey = b'\x03' + xpoint.num.to_bytes(32, 'big')
27+
28+
hsh160 = hash160(compressesKey)
29+
"""Prefix for Mainnet"""
30+
main_prefix = b'\x00'
31+
32+
newAddr = main_prefix + hsh160
33+
34+
"""Checksum"""
35+
checksum = hash256(newAddr)[:4]
36+
newAddr = newAddr + checksum
37+
BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
38+
39+
count = 0
40+
for c in newAddr:
41+
if c == 0:
42+
count += 1
43+
else:
44+
break
45+
46+
"""convert address to numeric form"""
47+
num = int.from_bytes(newAddr, 'big')
48+
prefix = '1' * count
49+
50+
result = ''
51+
while num > 0:
52+
num, mod = divmod(num, 58)
53+
result = BASE58_ALPHABET[mod] + result
54+
55+
PublicAddress = prefix + result
56+
return {"private Key": privateKey, "Public Address": PublicAddress}
57+
58+
59+
if __name__ == '__main__':
60+
account = Account()
61+
print(account.createKeys())

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ Under Backend, `core` and `util`.
77
Height, Blocksize, BlockHeader, TxCount, Txs` variables
88
3. Create a new module `blockheader.py`, create a class call `BlockHeader`. Inside the `__init__` method will take
99
`version, prevBlockHash, merkleRoot, timestamp, bits` and declare `self.nonce = 0 , self.blockHash = ''`
10-
4. Create a
10+
4.

0 commit comments

Comments
 (0)