Его немного большим, но я могу вставить его здесь, если кому-то интересно
Я заинтересован
Хорошо, здесь это. Я сделал это, главным образом, в качестве учебного упражнения, код почти все из pywallet.py так наконечник шляпы к jackjack.
# Bitaddr.py - печать Bitcoin адрес дали шестигранной секретный ключ
# В качестве бонуса сделать brainwallet кодирование слишком
# Объединяет код из ...
# Pywallet.py jackjack в
# https://github.com/jackjack-jj/pywallet
# https://bitcointalk.org/index.php?topic=23241.0
импорт hashlib
# Код от pywallet.py для кодирования bas58
__b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
__b58base = Len (__ b58chars)
Защиту b58encode (v):
""" закодировать v, который является строка байтов, в base58.
"""
LONG_VALUE = 0L
для (I, с) в Перечислим (V [:: - 1]):
LONG_VALUE + = (256 ** я) * Ord (с)
Результат = «»
в то время как LONG_VALUE >= __b58base:
ДИВ, мод = divmod (LONG_VALUE, __b58base)
Результат = __b58chars [мод] + результат
LONG_VALUE = DIV
Результат = __b58chars [LONG_VALUE] + результат
# Bitcoin делает немного опережените нулевое сжатие:
# Ведущих 0-байты на входе становятся ведущим-1s
NPAD = 0
для с в V:
если с == '\ 0': NPAD + = 1
еще: разрыв
возврата (__b58chars [0] * NPAD) + результат
Защиту b58decode (V, длина):
""" расшифровывает v в строку LEN байтов
"""
LONG_VALUE = 0L
для (I, с) в Перечислим (V [:: - 1]):
LONG_VALUE + = __b58chars.find (с) * (__b58base ** я)
Результат = «»
в то время как LONG_VALUE >= 256:
DIV, MOD = divmod (LONG_VALUE, 256)
Результат = CHR (моды) + результат
LONG_VALUE = DIV
Результат = CHR (LONG_VALUE) + результат
NPAD = 0
для с в V:
если с == __b58chars [0]: NPAD + 1 =
еще: разрыв
Результат = CHR (0) * NPAD + результат
если длина не является None и LEN (результат) = длина:
возвращения None
возвращаемый результат
# Конец реализации bitcointools base58
# https://bitcointalk.org/index.php?topic=23241.0
# На самом деле это тоже из pywallet.py
Класс CurveFp (объект):
Защиту __init __ (я, р, а, б):
само .__ р = р
само .__ а =
самостоятельно .__ Ь = Ь
Защита р (Я):
Самовозврат .__ р
DEF а (сам):
Самовозврат .__
Защиту б (Я):
Самовозврат .__ б
Защиту contains_point (я, х, у):
возвращение (у * у - (х * х * х + с собственной .__ а * х + с собственной .__ б))% собственной .__ р == 0
Класс Point (объект):
не Защита __init __ (самостоятельно, кривой, х, у, порядок = None):
самостоятельная .__ кривой = кривой
самостоятельно .__ х = х
само .__ у = у
самостоятельно .__ порядок = порядок
если само .__ кривая: утверждать, само .__ curve.contains_point (х, у)
если заказ: утверждать сам * заказ == INFINITY
Защиту __add __ (я, другое):
если иное == INFINITY: Самовозврат
если само == INFINITY: возвращение другого
утверждают само .__ кривой == другой кривой .__
если само .__ х == другой .__ х:
если (само .__ у + у друга .__)% собственной .__ curve.p () == 0:
возвращение INFINITY
еще:
вернуться self.double ()
р = Автономный .__ curve.p ()
л = ((другие .__ у - Самостоятельно .__ у) * \
inverse_mod (другой .__ х - само .__ х, р)) р%
x3 = (л * л - само .__ х - другой .__ х)% р
у3 = (л * (само .__ х - х3) - само .__ у)% р
точка возврата (само .__ кривая, x3, y3)
Защиту __mul __ (я, другое):
Защиту leftmost_bit (х):
утверждать х > 0
Результат = 1L
в то время как результат <= Х: результат = 2 * результат
возвращаемый результат / 2
е = другие
если само .__ порядок: е = е% собственной .__ заказа
если е == 0: возвращение INFINITY
если само == INFINITY: возвращение INFINITY
утверждать е > 0
e3 = 3 * е
negative_self = Точка (само .__ кривой, само .__ х, у -self .__, само .__ заказа)
я = leftmost_bit (е3) / 2
результат = сам
в то время как я > 1:
Результат = result.double ()
если (e3 & я)! = 0 и (е & я) == 0: результат = результат + самостоятельно
если (e3 & я) == 0 и (е & я) = 0: результат = результат + negative_self
I = I / 2
возвращаемый результат
Защиту __rmul __ (я, другое):
Самовозврат * другой
Защиту __str __ (Я):
если само == INFINITY: возвращение "бесконечность"
вернуть "(% D,% d)" % (Само .__ х, Self .__ у)
Защита двойной (сам):
если само == INFINITY:
возвращение INFINITY
р = Автономный .__ curve.p ()
а = само .__ curve.a ()
л = ((3 * само .__ х * само .__ х + а) * \
inverse_mod (2 * Self .__ у, р)) р%
x3 = (л * л - 2 * само .__ х)% р
у3 = (л * (само .__ х - х3) - само .__ у)% р
точка возврата (само .__ кривая, x3, y3)
Защиту х (Я):
Самовозврат .__ х
Защита у (Я):
Самовозврат .__ у
Защиту кривой (сам):
Самовозврат .__ кривую
Порядок четкости (Я):
Самовозврат .__ заказ
ИНФИНИТИ = Точка (Ничего, Ничего, ничего нет)
Защиту inverse_mod (а, м):
если < 0 или т <= А: а =% м
в, г = а, м
UC, VC, уд, VD = 1, 0, 0, 1
в то время как с = 0:
д, с, d = divmod (д, в) + (с,)
УНЦ, VC, уд, VD = уд - д * ис, VD - д * VC, УНЦ, ВК
утверждают, д == 1
если уд > 0: возвращение уд
еще: вернуть уд + т
# secp256k1
_p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2FL
_r = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141L
_b = 0x0000000000000000000000000000000000000000000000000000000000000007L
_а = 0x0000000000000000000000000000000000000000000000000000000000000000L
_Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798L
_Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8L
Класс Signature (объект):
Защиту __init __ (я, R, S):
self.r = г
self.s = ы
Класс Public_key (объект):
Защиту __init __ (я, генератор, пункт):
self.curve = generator.curve ()
self.generator = генератор
self.point = точка
п = generator.order ()
если не п:
поднять RuntimeError, "пункт Генератор должен иметь порядок."
если не п * точка == INFINITY:
поднять RuntimeError, "заказ точка Генератор плохо."
если point.x () < 0 или п <= Point.x () или point.y () < 0 или п <= Point.y ():
поднять RuntimeError, "Точка Генератора имеет й или у вне диапазона."
Защиту проверяет (самостоятельно, хэш, подпись):
G = self.generator
п = G.order ()
г = signature.r
s = signature.s
если г < 1 или г > п-1: возвращение Ложные
если с < 1 или с > п-1: возвращение Ложные
с = inverse_mod (с, п)
u1 = (хэш * с)% п
и2 = (г * в) п%
ху = u1 * G + u2 * self.point
v = ху.й ()% п
вернуться V == г
Класс private_key (объект):
Защиту __init __ (я, public_key, secret_multiplier):
self.public_key = public_key
self.secret_multiplier = secret_multiplier
Защита дер (Я):
hex_der_key = '06052b8104000a30740201010420' + \
'% 064x' % self.secret_multiplier + \
'A00706052b8104000aa14403420004' + \
'% 064x' % self.public_key.point.x () + \
'% 064x' % self.public_key.point.y ()
вернуть hex_der_key.decode ( 'шестигранной')
Защита знак (я, хэш, random_k):
G = self.public_key.generator
п = G.order ()
к = random_k% п
p1 = к * G
г = p1.x ()
если г == 0: поднять RuntimeError, "удивительно повезло случайное число г"
s = (inverse_mod (к, п) * \
(Хэш + (self.secret_multiplier * г)% п))% п
если s == 0: поднять RuntimeError, "удивительно повезло случайное число s"
Подпись возврата (R, S)
curve_256 = CurveFp (_p, _о, _b)
generator_256 = Точка (curve_256, _Gx, _Gy, _r)
г = generator_256
Защиту hexprivkey2addr (privkey_hex):
печать privkey_hex, " собств ключ HEX"
# Кодировать закрытый ключ в WIF см https://en.bitcoin.it/wiki/Base58Check_encoding
data_hex = "80" + privkey_hex
data_bin = data_hex.decode ( 'шестигранной')
хэш = hashlib.sha256 (hashlib.sha256 (data_bin) .digest ()). дайджеста ()
sha_hex = hash.encode ( 'hex_codec')
step2_hex = data_hex + sha_hex [8]
privkey = b58encode (step2_hex.decode ( 'шестигранной'))
печать privkey, " Секретный ключ WIF"
# Теперь печать сжатого WIF закрытого ключа
# Bitaddress.org присоединяет 01 так попробовать, что ...
data_hex = "80" + Privkey_hex + "01"
data_bin = data_hex.decode ( 'шестигранной')
хэш = hashlib.sha256 (hashlib.sha256 (data_bin) .digest ()). дайджеста ()
sha_hex = hash.encode ( 'hex_codec')
step2_hex = data_hex + sha_hex [8]
privkey = b58encode (step2_hex.decode ( 'шестигранной'))
печать privkey, " закрытый ключ WIF (ср)"
# ===========================================
# Следующий шаг заключается в преобразовании с открытым ключом
# ===========================================
секрет = INT (privkey_hex, 16) # Нужно это как десятичное число
# Генерировать Публичный
Публичный = Public_key (г, г секрет *)
# Печать 'Публичные', шестигранный (pubkey.point.x ()), шестигранный (pubkey.point.y ())
# Это неуклюжее, есть, вероятно, лучший способ ...
x_hex = гекс (pubkey.point.x ())
x_hex = x_hex [2:] # Удалить ведущих 0x
x_hex = x_hex [: - 1] # Удалить задний L
# Pad с ведущими 0-х до 64 символов ...
x_hex = x_hex.zfill (64)
# Распечатать "Икс", x_hex
y_hex = гекс (pubkey.point.y ())
y_hex = y_hex [2:] # Удалить ведущих 0x
y_hex = y_hex [: - 1] # Удалить задний L
# Возможно, нужно раздуть с ведущими 0-х до 64 символов ...
y_hex = y_hex.zfill (64)
# Распечатать "Y", y_hex
pubkey_hex = "04" + X_hex + y_hex
печать pubkey_hex, " открытый ключ"
# ==================
# Поколение Адрес
# ==================
Публичный = pubkey_hex
data_bin = pubkey.decode ( 'шестигранной')
# Первая стадия представляет собой SHA256
data_bin = hashlib.sha256 (data_bin) .digest ()
# Второй шаг ripemd160
хэш = hashlib.new ( 'ripemd160')
hash.update (data_bin)
hash_digest = hash.digest ()
hash_hex = hash.hexdigest ()
печать hash_hex + " несжатый хэш (Публичный)"
# Теперь закодировать адрес
data_hex = "00" + hash_hex # 00 это версия байт, также может быть 05
data_bin = data_hex.decode ( 'шестигранной')
хэш = hashlib.sha256 (hashlib.sha256 (data_bin) .digest ()). дайджеста ()
sha_hex = hash.encode ( 'hex_codec')
step2_hex = data_hex + sha_hex [8]
печать b58encode (step2_hex.decode ( 'шестигранной')), " адрес"
# ================================================= ===========================================
# Теперь сделайте то же самое для СЖАТЫХ открытого ключа (см https://bitcointalk.org/index.php?topic=205490.0)
# ================================================= ===========================================
lastchar = Публичный [-2:]
Val = lastchar.decode ( 'шестигранной')
если (Ord (Val)% 2):
# Распечатать "странный"
xpubkey = "03" + Публичные [2:66]
еще:
# Распечатать "даже"
xpubkey = "02" + Публичные [2:66]
печать xpubkey + " Комп Публичных"
data_bin = xpubkey.decode ( 'шестигранной')
# Первая стадия представляет собой SHA256
data_bin = hashlib.sha256 (data_bin) .digest ()
# Второй шаг ripemd160
хэш = hashlib.new ( 'ripemd160')
hash.update (data_bin)
hash_digest = hash.digest ()
hash_hex = hash.hexdigest () # Сохраняет шаг кодирования
печать hash_hex + " хэш (сжатый Публичных)"
# Теперь закодировать адрес
data_hex = "00" + hash_hex # 00 это версия байт, также может быть 05
data_bin = data_hex.decode ( 'шестигранной')
хэш = hashlib.sha256 (hashlib.sha256 (data_bin) .digest ()). дайджеста ()
sha_hex = hash.encode ( 'hex_codec')
step2_hex = data_hex + sha_hex [8]
печать b58encode (step2_hex.decode ( 'шестигранной')), " сжатый адрес"
Защиту brainwallet (ключевая фраза):
Распечатать "= ключевая фраза [" + + Ключевая фраза "]"
privkey_bin = hashlib.sha256 (ключевая фраза) .digest () # Single sha256 (стандартный алгоритм мозга)
# Privkey_bin = hashlib.sha256 (privkey_bin) .digest () # Double sha256 (не полезно)
# Privkey_hex = hashlib.sha256 (ключевая фраза) .hexdigest () # Может генерировать гекс непосредственно
privkey_hex = privkey_bin.encode ( 'hex_codec') # В качестве альтернативы из бен
hexprivkey2addr (privkey_hex)
# ============================= главный =================== ===========
если __name__ == "__главный__":
# Примеры
hexprivkey2addr ("0000000000000000000000000000000000000000000000000000000000000001")
Распечатать
hexprivkey2addr ("00000000000000000000000000000000000000000000000000000000000000b6") # Имеет адрес на 11 префиксов
Распечатать
hexprivkey2addr ("deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef")
Распечатать
brainwallet ("правильная лошадь батареи штапельного")