比特币钱包: 300 描述

来到中国后,米特尼克 身无分文了,怎样赚一大笔钱以备不时之需呢?比特币的爆发引起了他的注意。FBI 从丝绸之路缴获的大量比特币成了他的目标,他也想借此机会嘲笑一下 FBI。不费吹灰之力,他就搞定了这笔比特币巨款。你知道他是怎么搞定的吗?http://bctf.cn/files/downloads /robotum_9332cfdb5e503889e24e757d962a7454.html

提示

1. 机器人的眼睛是一个时钟,时钟是会走的阿,亲!2. 要做出此题,请先研究清楚比特币地址签名机制和 warpwallet 的用途3. 邮件发送格式说明,邮件内容那一行千万别写中文,verify 的部分不包含首尾的空格和回车(也就是 strip),下面的 signature 是 base64 串,可以使用 bitcoin-qt 客户端进行 sign 和 verify message 来验证 http://bctf.cn/files/downloads/robotum_9332cfdb5e503889e24e757d962a7454.html内容如下

嘿!你们好!

我是 FBI 的比特币守护机器人,我的地址是 [email protected], 我正在守护着 FBI 的一个重要比特币地址 1Atk95NnaQDiegEkqjJvg6c2KkJbSr2BEL (听说里面有很多钱!)。

你们知道吗?最近我学会了使用 Warpwallet,它既简单,又强大,还易于使用。哈哈!你们肯定没法猜到我的密钥是什么,不要偷窥哦。

好了,如果我的主人想取回存储在我这里的机密信息的话,只需要向我发送邮件就可以了。当然,邮件要使用这个重要比特币地址来签名,另外,你还要告诉我你想要取什么东西,只有让我验证通过了我才能告诉你。

为了避免忘记,我再重复一遍邮件的格式。

—–BEGIN BITCOIN SIGNED MESSAGE—–
这里写邮件的内容啦!
—–BEGIN SIGNATURE—–
这里是签名串
—–END BITCOIN SIGNED MESSAGE—–

祝你们好运!

这道题完全是靠第一个提示做出来的。。。 在那个网页中发现机器人用的是Warpwallet,于是先google下 https://keybase.io/warp/warp_1.0.6_SHA256_e68d4587b0e2ec34a7b554fbd1ed2d0fedfaeacf3e47fbb6c5403e252348cbfc.html 这个是通过Warpwallet用Passphrase和salt生产比特币地址(公钥)和private key 同时还有相关算法的说明 推 测salt应该就是那个机器人的email,那passphrase呢。。。看第一个提示,猜测是个时间然后就用这个算法找碰撞。。。一开始只从时钟上的 时间试到12点,没跑出来,后面把所有时间都跑了。。结果出了结果20:20,然后就能跑出他的private key啦 算法的代码是github上来的

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
#!/usr/bin/env python
#
#
\# Description: Implements the WarpWallet algorithm as descibed below:
#
\# s1 = scrypt(key=(passphrase||0x1), salt=(salt||0x1), N=2^18, r=8, p=1, dkLen=32)
\# s2 = pbkdf2(key=(passphrase||0x2), salt=(salt||0x2), c=2^16, dkLen=32, prf=HMAC_SHA256)
\# keypair = generate\_bitcoin\_keypair(s1 xor s2)
#
#modified by ROIS_yufan for BCTF2013 crypto300
import argparse
import binascii
import json
import scrypt
import sys
from passlib.utils import pbkdf2
from pycoin import ecdsa, encoding
from pycoin.ecdsa import secp256k1
class WarpWallet(object):
def \_\_init\_\_(self, pbkdf2\_count, derived\_key\_len, scrypt\_power, scrypt_p,
scrypt_r):
self.dklen = derived\_key\_len
self.pbkdf2\_count = pbkdf2\_count
self.scrypt\_power = scrypt\_power
self.scrypt\_r = scrypt\_r
self.scrypt\_p = scrypt\_p
def warp(self, passphrase, salt=""):
"""
Return dictionary of WarpWallet public and private keys corresponding to
the given passphrase and salt.
"""
s1 = binascii.hexlify(self._scrypt(passphrase, salt))
out = self._pbkdf2(passphrase, salt)
s2 = binascii.hexlify(out)
base = binascii.unhexlify(s1)
s3 = binascii.hexlify(self._sxor(base,out))
secret_exponent = int(s3, 16)
public\_pair = ecdsa.public\_pair\_for\_secret\_exponent(secp256k1.generator\_secp256k1, secret_exponent)
#private\_key = encoding.secret\_exponent\_to\_wif(secret_exponent, compressed=False)
public\_key = encoding.public\_pair\_to\_bitcoin\_address(public\_pair, compressed=False)
out = public_key
return out
def _scrypt(self, passphrase, salt=""):
scrypt_key = passphrase + "x01"
scrypt_salt = salt + "x01"
out = scrypt.hash(scrypt\_key, scrypt\_salt, N=2**self.scrypt_power,
r=self.scrypt\_r, p=self.scrypt\_p, buflen=self.dklen)
return out
def _pbkdf2(self, passphrase, salt=""):
hexlified_key = binascii.hexlify(passphrase) + "02"
pbkdf2\_key = binascii.unhexlify(hexlified\_key)
hexlified_salt = binascii.hexlify(salt) + "02"
pbkdf2\_salt = binascii.unhexlify(hexlified\_salt)
out = pbkdf2.pbkdf2(secret=pbkdf2\_key, salt=pbkdf2\_salt, keylen=self.dklen,
rounds=self.pbkdf2\_count, prf='hmac\_sha256')
return out
def _sxor (self, s1, s2):
# Convert strings to a list of character pair tuples,
# go through each tuple, converting them to ASCII code (ord),
# perform exclusive or on the ASCII code,
# then convert the result back to ASCII (chr),
# merge the resulting array of characters as a string.
return ''.join(chr(ord(a) ^ ord(b)) for a,b in zip(s1,s2))
def parse_args():
parser = argparse.ArgumentParser()
parser.add\_argument("-c", "--pbkdf2\_count",
help="iteration count",
type=int,
default=2**16)
parser.add_argument("-d", "--dklen",
help="derived key length",
type=int,
default=32)
parser.add\_argument("-n", "--scrypt\_power",
help="2^n passed as the 'N' param to scrypt",
type=int,
default=18)
parser.add\_argument("-p", "--scrypt\_p",
help="'p' param to scrypt",
type=int,
default=1)
parser.add\_argument("-r", "--scrypt\_r",
help="'r' param to scrypt",
type=int,
default=8)
parser.add_argument("-P", "--passphrase" ,
help="passphrase",
type=str)
parser.add_argument("-S", "--salt" ,
help="salt",
type=str)
args = parser.parse_args()
if not args.passphrase:
print "Must provide passphrase (-P)"
sys.exit(1)
if not args.salt:
print "Must provide salt (-S)"
sys.exit(1)
return args
if \_\_name\_\_ == "\_\_main\_\_":
f = open("c300dict.txt", 'r')
for line in f:
strpass = line.strip()
wallet = WarpWallet(2**16, 32, 18,1, 8)
str = wallet.warp(strpass, salt)
if str == '1Atk95NnaQDiegEkqjJvg6c2KkJbSr2BEL':
print 'get!', strpass
break
print line

然后签名发邮件就ok啦,注意按题目要求的格式发。 http://p2pbucks.com/tools/brainwallet/index.html#sign