BlockChain-Account_TakeOver

题目描述

题目描述

ECDSA

签名

假设我们的私钥为 d A d_A dA而公钥为 Q A Q_A QA Q A = d A ⋅ G Q_A=d_A\cdot G QA=dAG,接下来就是签名的过程,要签名的消息为 m m m

  1. e = H A S H ( m ) e = HASH(m) e=HASH(m)
  2. e e e的左边的 L n L_n Ln个bit长度的值为 z z z L n L_n Ln即为前面提到的参数里 n n n的比特长度
  3. [ 1 , n − 1 ] [1, n-1] [1,n1]范围内,随机选择一个整数 k k k
  4. 利用 k k k得到椭圆曲线上的一点 ( x 1 , y 1 ) = k ⋅ G (x1,y1)=k \cdot G (x1y1)=kG
  5. 然后计算 r ≡ x 1 ( m o d n ) r \equiv x_1 (mod n) rx1(modn),如果如果 r = 0 r=0 r=0则返回步骤3重新选择 k k k
  6. 计算 s = k − 1 ( z + r ⋅ d A ) ( m o d n ) s = k^{-1}(z + r\cdot d_A) (mod n) s=k1(z+rdA)(modn),如果 s = 0 s=0 s=0则返回步骤3重新选择 k k k
  7. 得到的数字签名即为 ( r , s ) (r,s) (rs)

验证

取点 P = ( X p , Y p ) = s − 1 ⋅ z ⋅ G + s − 1 ⋅ r ⋅ Q A P=(X_p,Y_p)= s ^ {-1} \cdot z \cdot G + s ^ {-1} \cdot r \cdot Q_A P=(Xp,Yp)=s1zG+s1rQA
X p = r X_p=r Xp=r,则签名有效,否则无效

Simple Proof
P = ( X p , Y p ) = s − 1 ⋅ z ⋅ G + s − 1 ⋅ r ⋅ Q A P=(X_p,Y_p)= s ^ {-1} \cdot z \cdot G + s ^ {-1} \cdot r \cdot Q_A P=(Xp,Yp)=s1zG+s1rQA
因为 Q A = d A ⋅ G Q_A=d_A \cdot G QA=dAG,故有
P = s − 1 ⋅ z ⋅ G + s − 1 ⋅ r ⋅ Q A P= s ^ {-1} \cdot z \cdot G + s ^ {-1} \cdot r \cdot Q_A P=s1zG+s1rQA
= s − 1 ⋅ z ⋅ G + s − 1 ⋅ r ⋅ d A ⋅ G = s ^ {-1} \cdot z \cdot G + s ^ {-1} \cdot r \cdot d_A \cdot G =s1zG+s1rdAG
= s − 1 ⋅ G ⋅ ( z + r ⋅ d A ) = s ^ {-1} \cdot G \cdot {(z + r \cdot d_A)} =s1G(z+rdA)
又有 s = k − 1 ( z + r ⋅ d A ) ( m o d n ) s = k^{-1}(z + r\cdot d_A) (mod n) s=k1(z+rdA)(modn)
s − 1 = k ⋅ ( z + r ⋅ d A ) − 1 ( m o d n ) s^{-1} = k\cdot(z + r\cdot d_A)^{-1} (mod n) s1=k(z+rdA)1(modn)
代入得到 P = k ⋅ G P=k \cdot G P=kG

利用冲突的随机数恢复私钥

从上面的签名过程我们可以看到最关键的地方就在于随机数k,对于一个固定的椭圆曲线,一个确定的k就意味着一个确定的r,所以如果有两个相同的私钥签署的签名出现了相同的r就代表着在生成随机数时取到了相同的k,看到这里想必你也明白了我们题目的交易签名的问题出在哪了,这两笔交易的r值相同,代表在它们签名时使用的随机数k是相同的,而这就是我们恢复私钥的关键
我们不妨设这两个签名的 z z z s s s分别为 z 1 z_1 z1 z 2 z_2 z2 s 1 s_1 s1 s 2 s_2 s2
则有
s 1 − s 2 = k − 1 ( z 1 + d A ⋅ r ) − k − 1 ( z 2 + d A ⋅ r ) s_1-s_2= k ^ {-1}(z_1 + d_A \cdot r)-k ^ {-1}(z_2+ d_A \cdot r) s1s2=k1(z1+dAr)k1(z2+dAr)
= k − 1 ( z 1 − z 2 ) = k ^ {-1}(z_1 - z_2) =k1(z1z2)
那么 k = ( z 1 − z 2 ) ( s 1 − s 2 ) k = \frac {(z_1-z_2)}{(s_1-s_2)} k=(s1s2)(z1z2)
通过 k k k,可以计算出 d A = ( s ⋅ k − z ) / r d_A=(s \cdot k -z) /r dA=(skz)/r

P2PKH

p2pkh
PubkeyScript是一张记录了交易记录的指令列表,它控制了下一名使用者如何解锁已接收的比特币并传送。收款人会制造一个signature script,而该文件必须满足最后一个发送者创建的PubkeyScript的参数。
PubkeyScript的参数:

  1. 公钥哈希(Public Key Hash) (比特币地址)
  2. 电子签署(ScriptSig: (r,s)+pubkey)

ASM是汇编代码

  1. OP_PUSHBYTES_71指压入栈中一个71字节大小的数据
  2. nSequence用以记录该笔交易是否可以上链
  3. Previous output Script用以验证当前用于支付的比特币的来源
  4. ScriptPubKey是一个脚本,用以验证当前用户有能力使用这个UTXO中的比特币来支付,即证明身份
    OP_DUP复制栈顶数据
    OP_HASH160先后进行两种hash操作然后压入栈
    OP_PUSHBYTES_20将签名的hash值压入栈
    OP_EQUALVERIFY比较计算签名hash和刚压入栈的hash来验证有效性,有效返回1否则返回0
    OP_CHECKSIG检测栈顶的2个元素,pub key和signature是否能对应的上。对应的上,说明这个签名的私钥,和收款人的公钥可以对上。有资格花这笔钱
    OP_RETURN 用来当注释,携带一些信息
    Transaction hex则包含所有信息连接在一起

求解过程

提取r,s,z

脚本来源

# -*-coding:utf-8-*-
"""
@author: iceland
"""
import sys
import hashlib
import argparse
from urllib.request import urlopen# # ==============================================================================
# parser = argparse.ArgumentParser(
#     description='This tool helps to get ECDSA Signature r,s,z values from Bitcoin rawtx or txid',
#     epilog='Enjoy the program! :)    Tips BTC: bc1q39meky2mn5qjq704zz0nnkl0v7kj4uz6r529at')
#
# parser.add_argument("-txid", help="txid of the transaction. Automatically fetch rawtx from given txid", action="store")
# parser.add_argument("-rawtx", help="Raw Transaction on the blockchain.", action="store")
#
# if len(sys.argv) == 1:
#     parser.print_help()
#     sys.exit(1)
# args = parser.parse_args()
# # ==============================================================================
#
# txid = args.txid if args.txid else ''
# rawtx = args.rawtx if args.rawtx else ''
#
# if rawtx == '' and txid == '':
#     print('One of the required option missing -rawtx or -txid');
#     sys.exit(1)# ==============================================================================def get_rs(sig):rlen = int(sig[2:4], 16)r = sig[4:4 + rlen * 2]#    slen = int(sig[6+rlen*2:8+rlen*2], 16)s = sig[8 + rlen * 2:]return r, sdef split_sig_pieces(script):sigLen = int(script[2:4], 16)sig = script[2 + 2:2 + sigLen * 2]r, s = get_rs(sig[4:])pubLen = int(script[4 + sigLen * 2:4 + sigLen * 2 + 2], 16)pub = script[4 + sigLen * 2 + 2:]assert (len(pub) == pubLen * 2)return r, s, pub# Returns list of this list [first, sig, pub, rest] for each input
def parseTx(txn):if len(txn) < 130:print('[WARNING] rawtx most likely incorrect. Please check..')sys.exit(1)inp_list = []ver = txn[:8]if txn[8:12] == '0001':print('UnSupported Tx Input. Presence of Witness Data')sys.exit(1)inp_nu = int(txn[8:10], 16)first = txn[0:10]cur = 10for m in range(inp_nu):prv_out = txn[cur:cur + 64]var0 = txn[cur + 64:cur + 64 + 8]cur = cur + 64 + 8scriptLen = int(txn[cur:cur + 2], 16)script = txn[cur:2 + cur + 2 * scriptLen]  # 8b includedr, s, pub = split_sig_pieces(script)seq = txn[2 + cur + 2 * scriptLen:10 + cur + 2 * scriptLen]inp_list.append([prv_out, var0, r, s, pub, seq])cur = 10 + cur + 2 * scriptLenrest = txn[cur:]return [first, inp_list, rest]# ==============================================================================
def get_rawtx_from_blockchain(txid):try:htmlfile = urlopen("https://blockchain.info/rawtx/%s?format=hex" % txid, timeout=20)except:print('Unable to connect internet to fetch RawTx. Exiting..')sys.exit(1)else:res = htmlfile.read().decode('utf-8')return res# =============================================================================def getSignableTxn(parsed):res = []first, inp_list, rest = parsedtot = len(inp_list)for one in range(tot):e = firstfor i in range(tot):e += inp_list[i][0]  # prev_txide += inp_list[i][1]  # var0if one == i:e += '1976a914' + HASH160(inp_list[one][4]) + '88ac'else:e += '00'e += inp_list[i][5]  # seqe += rest + "01000000"z = hashlib.sha256(hashlib.sha256(bytes.fromhex(e)).digest()).hexdigest()res.append([inp_list[one][2], inp_list[one][3], z, inp_list[one][4], e])return res# ==============================================================================
def HASH160(pubk_hex):return hashlib.new('ripemd160', hashlib.sha256(bytes.fromhex(pubk_hex)).digest()).hexdigest()# ==============================================================================txn = '010000000153db4e56f159c0679818ef8ce814ce8fcaad12b854da7e582fb5f19266945f63000000006a47304402200e1e942f62d61cc25117d71bc2da4b523bd720dc7feec77551a0b152eb042cd7022030d7d78612b765dff96dd14fc5d723e06a8fa61b42a93410236273baf82f7f15012102572263bbac032e37cf96fe7664fb799f56353108c032807cc23ca557fb60b394ffffffff02d0070000000000001976a914b1c75a61c0461cd92c124e00ee275a600aa096b288ac0000000000000000056a0343544600000000'
# if rawtx == '':
#     rawtx = get_rawtx_from_blockchain(txid)print('\nStarting Program...')m = parseTx(txn)
e = getSignableTxn(m)for i in range(len(e)):print('=' * 70,f'\n[Input Index #: {i}]\n     R: {e[i][0]}\n     S: {e[i][1]}\n     Z: {e[i][2]}\nPubKey: {e[i][3]}')

求dA

#-*-coding:utf-8-*-
r1 = 0x0e1e942f62d61cc25117d71bc2da4b523bd720dc7feec77551a0b152eb042cd7
s1 = 0x5611099541793c7681a9f8b48364d6e7088e16afe7b7b6244c52e94d28252a3b
z1 = 0x5ecd4154a2db20480d7715d6e47a772aaf596e11e6f16a4d58e9f0d260294660r2 = 0x0e1e942f62d61cc25117d71bc2da4b523bd720dc7feec77551a0b152eb042cd7
s2 = 0x30d7d78612b765dff96dd14fc5d723e06a8fa61b42a93410236273baf82f7f15
z2 = 0x50f1c6205aab5f8dac7b505f91dfc437b1b13cd00f12a492570a040a27c38e25assert r1 == r2
r = r1
def inverse_mod( a, m ):"""Inverse of a mod m."""if a < 0 or m <= a: a = a % mc, d = a, muc, vc, ud, vd = 1, 0, 0, 1while c != 0:q, c, d = divmod( d, c ) + ( c, )uc, vc, ud, vd = ud - q*uc, vd - q*vc, uc, vcassert d == 1if ud > 0: return udelse: return ud + mdef derivate_privkey(p, r, s1, s2, z1, z2):z = z1 - z2s = s1 - s2r_inv = inverse_mod(r, p)s_inv = inverse_mod(s, p)k = (z * s_inv) % pd = (r_inv * (s1 * k - z1)) % preturn d, kp  = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141privatekey,k=derivate_privkey(p,r,s1,s2,z1,z2)

利用私钥解密AES

import base64
cipher = base64.b64decode(b"4w/VLHqPZi/epoOGvjoY9TZWhDtYpL3iLsUTyvzghJM=")
privatekey = 0xF41AA419CB6BD43F322D403F40728CE9784CD0B465F409322A76A3DF0A984A29
from Crypto.Cipher import AES
from Crypto.Util.number import *
key = long_to_bytes(privatekey)[0:16]
iv = long_to_bytes(privatekey)[16:]
aes = AES.new(key=key,iv=iv,mode=AES.MODE_CBC)
flag = aes.decrypt(cipher.encode())
print(flag)

参考链接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/39719.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

02_Lock锁

首先看一下JUC的重磅武器——锁&#xff08;Lock&#xff09; 相比同步锁&#xff0c;JUC包中的Lock锁的功能更加强大&#xff0c;它提供了各种各样的锁&#xff08;公平锁&#xff0c;非公平锁&#xff0c;共享锁&#xff0c;独占锁……&#xff09;&#xff0c;所以使用起来…

block()/blockFirst()/blockLast() 解决办法

定位到BlockingLoadBalancerClient.java 155行 出问题的点代码如下&#xff1a; Response<ServiceInstance> loadBalancerResponse Mono.from(loadBalancer.choose(request)).block();将这段修改为异步解决&#xff1a; 新建一个新的类 import org.springframework.c…

对Openai Chat API的一些理解

目录 偷懒的编写一个API 如何让ChatGPT理解我们都在聊什么 付费和一些注意事项 Create chat completion 最近ChatGPT这么火&#xff0c;那必须来凑个热闹啊。 申请账户我就不多说了&#xff0c;懂得都懂。 偷懒的编写一个API 从ChatGPT的Chat演示看&#xff0c;他需要一…

借AI之势,打破创意与想象的边界

IMMENSE、36氪&#xff5c;作者 01 “未来是属于AI的” 3月2日&#xff0c;内容创作圈大地震。 就在3月2日凌晨&#xff0c;OpenAI宣布开放ChatGPT本体模型API&#xff0c;其价格为1k tokens/$0.002。也就是说&#xff0c;从这一天开始&#xff0c;任何企业都能让ChatGPT为自…

谷歌的Bard怎么样?

Bard是什么&#xff1f; ChatGPT&#xff1a; Bard可以指以下几种事物&#xff1a; Bard是一个英雄联盟&#xff08;League of Legends&#xff09;游戏中的角色名称&#xff0c;他是一个能够进行攻击和治疗的辅助英雄。 Bard是指中世纪欧洲的一类文学艺术家&#xff0c;主要从…

实测「360智脑」的真正实力:能否领跑国内百“模”大战?

ChatGPT 的发布&#xff0c;无疑掀起了一股“AI 技术”新浪潮。百度文心一言、华为盘古、商汤日日新、阿里通义千问、讯飞星火等众多大模型的接连问世&#xff0c;使得国内的“百模之战”进入了前所未有的白热化阶段。无论是各大互联网巨头&#xff0c;还是清华、复旦等知名高校…

不止Chat,GPT-4 将释放更大生产力

目录 1.对 ChatGPT 的巨大超越 2.与 ChatGPT 相同的技术路线 3.GPT-4 背后的强大阵容 4.开启多模态大模型时代 相比 ChatGPT 能力有大进化&#xff0c;多模态上有突破但不多。 近日&#xff0c;多模态大模型 GPT-4 震撼登场&#xff01; GPT-4 能够接受图像和文本输入&am…

LoRA大模型加速微调和训练算法

ChatGPT带领着大模型像雨后春笋一般层出不穷&#xff0c;大家都对大模型微调跃跃欲试&#xff0c;现在咱们聊聊其中的常见的算法 1 LORA 低秩适应 理论 Lora( Low-Rank Adaotation)&#xff0c;低秩自适应模型微调的方法&#xff0c;它冻结预训练模型的权重&#xff0c;并将…

数据规模缩小 200 倍!指令微调高效指导大模型学习

夕小瑶科技说 原创 作者 | 智商掉了一地、Python 最近大型语言模型&#xff08;LLMs&#xff09;的指令微调备受研究人员的关注&#xff0c;因为它可以开发 LLM 遵循指令的潜力&#xff0c;使其更加符合特定的任务需求。虽然指令微调&#xff08;Instruction Tuning&#xff…

ChatGPT是否可以写出一篇论文

利用AI反哺教育和学术&#xff0c;在训练它写论文的过程中你学到的&#xff0c;比你自己写一篇论文学到的更多。让工具回归工具&#xff0c;让我们变成更好的我们&#xff01; 第一步&#xff1a;现象确认 第二步&#xff1a;学术概念化 第三步&#xff1a;定位优质的学术资源 …

网页版即时通讯聊天工具,支持主流浏览器,无需安装即可使用

基于信贸通即时通讯系统开发的网页版即时通讯&#xff0c;无需安装支持主流浏览器在线直接运行。可以与电脑版本和手机版本互通。支持文本聊天&#xff0c;标签&#xff0c;图片&#xff0c;文件传输&#xff0c;还支持位置接收等。 特点&#xff1a; 1、简单快速的集成到自己…

Ims跟2/3G会议电话(Conference call)流程差异介绍

2/3G Conference call 合并(Merged)通话前,两路电话只能一路保持(Hold),一路通话(Active)。 主叫Merged操作,Hold的一路会变成Active,进入会议通话。 例如终端A跟C通话,再跟B通话,此时B就是Active状态,C从Active变成Hold状态。Merged进入会议通话后,C又从Hold变…

英文学术会议参会必读-青年学者会议和演讲英语指南

本书介绍 本书讨论并展示在学术会议上使用的英语话语的类型&#xff0c;并从多角度为准会议参与者提供了指导。它是根据参加的众多学术会议的研究结果和作者的观察结果而得出的&#xff0c;基于对应用语言学的公认研究方法&#xff0c;以及针对学生&#xff0c;ESP老师&#xf…

jitsi-meet 主持人退出会议后结束会议室(网页访问)

实现功能&#xff1a; 当主持人退出当前会议后&#xff0c;要求参与会议的其他人员也都退出当前会议。 修改代码&#xff1a; 修改后&#xff0c;通过make编译代码。 将css/all.css 和 libs文件夹下的文件上传至会议服务器的对应目录下。重启会议服务器即可。 /usr/share/ji…

chatgpt赋能python:Python根据IP地址获取地理位置

Python根据IP地址获取地理位置 随着全球化的发展&#xff0c;网络已经成为人们获取信息和交流的主要渠道。在网站的开发和运营中&#xff0c;了解访问者的地理位置和所处时区是非常重要的。这样可以更好地定位目标受众并制定针对性的营销策略。本文将介绍如何使用Python根据IP…

一文读懂信息量、信息熵、相对熵(KL散度)和交叉熵

在人工智能深度学习的应用中&#xff0c;损失函数绝对是模型网络学习质量的关键。我们使用损失函数来表示的真实值与预测值之间的距离&#xff0c;进而指导模型的收敛方向。对于标量来说&#xff0c;我们能够很容易想到使用方差来描述误差。那么&#xff0c;如何表示向量之间的…

面板数据进行熵值法

面板数据熵值法分析流程如下&#xff1a; 一、案例背景 当前有9家公司连续5年&#xff08;2018-2022年&#xff09;的财务指标数据&#xff0c;想要通过这份数据&#xff0c;确定各个财务指标的权重。熵值法根据指标离散程度确定赋权大小&#xff0c;客观公正准确度高。本次收…

跨数据中心下的 Kafka 高可用架构分析

导语 本文介绍了 Kafka 跨数据中心的两种部署方式&#xff0c;简要分析两种方式下的不同架构以及优缺点&#xff0c;对这些架构可能碰到的问题也提供了一些解决思路&#xff1b;同时也说明了 Kafka 跨数据中心部署的社区解决方案和商业化解决方案。 背景 Kafka 作为世界上最…

分布式的流处理平台Kafka

目录&#xff1a; 一、简介二、基本概念三、生产者使用详解四、发送消息五、消费者代码示例 一、简介 ApacheKafka 是一个分布式的流处理平台。它具有以下特点&#xff1a; 支持消息的发布和订阅&#xff0c;类似于 RabbtMQ、ActiveMQ 等消息队列&#xff1b;支持数据实时处理…

熵_相对熵_散度

1 信息量 意外越大&#xff0c;越不可能发生&#xff0c;概率就越小&#xff0c;信息量也就越大&#xff0c;也就是信息越多。比如说“今天肯定会天黑”&#xff0c;实现概率100%&#xff0c;说了和没说差不多&#xff0c;信息量就是0。 详见&#xff1a;2. 信息量 1.1 公式 …