CIYAM (OP)
Legendary
Offline
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
|
|
October 13, 2012, 02:17:06 AM Last edit: October 14, 2012, 01:37:15 PM by CIYAM Pty. Ltd. |
|
There have been numerous threads discussing how to generate offline wallets and typically the problem ends up being that if your keys a) generated from a password or b) stored in clear text on a disk then they are subject to attack keyloggers or malware.
I am wondering if using GPG would provide a simple solution by having the output of vanitygen encrypted to a GPG public key (the private key not being known to the "offline" system). With this approach even if the "offline" system was stolen no generated private keys could be taken (apart from the GPG key which is actually of no consequence).
I will probably put together a small script/program to accomplish this but I guess if the GPG functionality could be built in to vanitygen itself this would be even more secure (i.e. so the private key is never output as clear text).
(see source in posts below)
|
|
|
|
Buffer Overflow
Legendary
Offline
Activity: 1652
Merit: 1016
|
|
October 13, 2012, 02:28:08 AM |
|
I thought there was an command line option to encrypt output from vanitygen already. I might be wrong though and thinking of some other program.
|
|
|
|
CIYAM (OP)
Legendary
Offline
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
|
|
October 13, 2012, 02:51:02 AM |
|
I thought there was an command line option to encrypt output from vanitygen already. I might be wrong though and thinking of some other program.
Really - using GPG (and only the private key to be encrypted)? (certainly not the version that I am running but it is probably a bit old)
|
|
|
|
CIYAM (OP)
Legendary
Offline
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
|
|
October 13, 2012, 04:07:32 AM |
|
Anyway for anyone that is interested I've whipped up a little utility and a couple of scripts to accomplish this (for Windows). Assuming you have GPG installed (with your public key in its keyring) create a dummy key-pair (I've used sample@domain.com here) and give it the password "password". First part is a simple tool (probably could just be a shell script in Linux) which firstly sends a hard-coded password to cout (the security of the GPG "from" should be irrelevant as it being used as a "send only" address) followed by the private key line it finds from cin (it is expecting its cin to be coming from "vanitygen"). The "address" line is output to a fixed filename ("x" in this source). [x.cpp]
#include <string> #include <fstream> #include <iostream>
const char* const c_outfile = "x"; const char* const c_password = "password";
const char* const c_address_prefix = "Address: "; const char* const c_privkey_prefix = "Privkey: ";
using namespace std;
int main( ) { ofstream outf( c_outfile );
cout << c_password << endl;
string str, addr, privkey; while( getline( cin, str ) ) { if( str.find( c_address_prefix ) == 0 ) outf << str << '\n' << endl; else if( str.find( c_privkey_prefix ) == 0 ) cout << str << endl; } }
The second part is a batch file you call in order to create a new bitcoin address (change Ian to your own GPG name): @echo off
REM *** Use simple program to split out the private key for GPG encryption. vanitygen 1 | x.exe | gpg --armor --recipient Ian --encrypt --sign --local-user sample@domain.com --batch --passphrase-fd 0 >y copy /Y x + y z >nul type z&del x y
REM *** Now rename the output file to the bitcoin address. type z | find "Address: " > z.bat cscript findrep.vbs z.bat "Address: " "ren z " >nul call z.bat del z.bat
The final part is the "findrep.vbs" tool (wouldn't be needed if using Linux): Const ForReading = 1 Const ForWriting = 2
If Wscript.Arguments.Count > 2 Then
strFileName = Wscript.Arguments(0) strOldText = Wscript.Arguments(1) strNewText = Wscript.Arguments(2)
Set objFSO = CreateObject("Scripting.FileSystemObject") Set objFile = objFSO.OpenTextFile(strFileName, ForReading)
strText = objFile.ReadAll objFile.Close strNewText = Replace(strText, strOldText, strNewText)
Set objFile = objFSO.OpenTextFile(strFileName, ForWriting) objFile.WriteLine strNewText objFile.Close
Else Wscript.Echo "Usage: findrep <file> <findstr> <replace>" Wscript.Quit End If
So now to generate a new bitcoin address you just type "genaddr" at the command prompt. As well as displaying the address and the GPG encrypted private key it saves the output to a file which is the name of the address (which can be safely backed up anywhere). The following a sample of the output: Address: 16vKwvg61UycrbhygXokVNQE3CxMSx22r7
-----BEGIN PGP MESSAGE----- Version: GnuPG v1.4.9 (MingW32)
hQEMA1cEJ0zSVDDtAQgAnagg9KrfhOlyZrSrItrQxB0IuoOnR8GmG0m4dXFYMCtY 2g4b1HEBhQ/xytGW+lon2LyRZpCoW5BAglW+NeFJ5Oev2c3XcBpVIDlwl9C4CsUJ w7/dUzFzqwfyiyDl662Bq8rF0qzOyQoyaj629Wz2EeBslb7yVejkg6mylc6hiPZz zTMxr4Qz4GByty5Qx1Z5X78h49zzeZHnm+22PoiP/5CjEZgX8LohIhyrmJnTRHDJ 47/nRE8j3w45/ozj73KVMyQ936IoxvhpiaoMwTp3UQ8cxdU4xaJBz6MOnjFJn5DV G3/Td4YpvJuYtNRNOg9xRT5lq2x0/71mYxN+4hoItNLACwFJyFrjitExf6du3Xyy CvT+kclF73xFGcAA+OLqbbeF1wRqqMxWrYPy2fAORua2B/iWPZgIkLNcCfLFZtL4 pABGG5DV0D+Dh+kyvDf03l2iFe3v1aedUKJ4UFnrBa7me/cQcZSnl5xknNBZD1PY R5IY1rrBC6BJ+6DtffRREwlp3tLgECpVL/zSBUGqWx68tzOxSnuwubCd0Q1z61fq L1wfDfjat052eB0xqM7x335LUvBbAKQJ5XxEaJ56CsJsQP4oU9EXcXZrvg2I =A3f1 -----END PGP MESSAGE-----
When you decide to "redeem" the address simply use "gpg --decode" with the file to get the private key: gpg: encrypted with 2048-bit RSA key, ID D25430ED, created 2012-03-25 "Ian Knowles <ian@ciyam.com>" Privkey: 5K6X8kvffAUYewAnmAuGHLB4wAk4UH2aZ1NBHdBf2YyzkUqzqHH gpg: Signature made 10/13/12 12:08:32 using DSA key ID 8C155FBD gpg: Good signature from "Sample <sample@domain.com>"
|
|
|
|
guruvan
|
|
October 13, 2012, 09:49:32 AM |
|
Awesome. Been wanting this exact tool for some time.
Any chance of porting it to linux?
|
|
|
|
CIYAM (OP)
Legendary
Offline
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
|
|
October 13, 2012, 10:12:36 AM |
|
Awesome. Been wanting this exact tool for some time.
Any chance of porting it to linux?
Hmm... I guess if a small bounty were to be offered (is 1 btc too much to ask?) then I could become motivated enough to put together a bash script.
|
|
|
|
Buffer Overflow
Legendary
Offline
Activity: 1652
Merit: 1016
|
|
October 13, 2012, 10:15:31 AM |
|
I thought there was an command line option to encrypt output from vanitygen already. I might be wrong though and thinking of some other program.
Sorry, must of been thinking of some other program.
|
|
|
|
CIYAM (OP)
Legendary
Offline
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
|
|
October 14, 2012, 04:54:29 AM Last edit: October 14, 2012, 04:13:25 PM by CIYAM Pty. Ltd. |
|
I just realised that with only a little minor tweaking this approach can be turned into a "roll your own" 2 factor authentication system. The idea is to encrypt the bitcoin private key to one GPG public key and then pipe this into another GPG encryption to a second GPG public key. So if you generate the GPG private keys on separate hardware then both computers would need to be compromised in order for your bitcoin private key to be obtained. Obviously this could be extended to 3 factors or more (depending upon level of paranoia, available hardware and degree of laziness). Updated C++ program (takes an optional argument "2" to indicate it is being used as the second pipe): [x.cpp] #include <string> #include <fstream> #include <iostream>
const char* const c_outfile = "x"; const char* const c_password = "password";
const char* const c_address_prefix = "Address: "; const char* const c_privkey_prefix = "Privkey: ";
using namespace std;
int main( int argc, char* argv[ ] ) { cout << c_password << endl;
bool is_second = false; if( argc > 1 && string( argv[ 1 ] ) == "2" ) is_second = true;
string str; while( getline( cin, str ) ) { if( is_second ) cout << str << '\n'; else if( str.find( c_address_prefix ) == 0 ) { ofstream outf( c_outfile ); outf << str << '\n' << endl; } else if( str.find( c_privkey_prefix ) == 0 ) cout << str << endl; } }
Updated batch file to create GPG encrypt the private key twice (thus requiring both GPG keys in order to decrypt the bitcoin private key) - change Ian_1 and Ian_2 to your own two different public GPG key names: [genaddr.bat] @echo off setlocal
set GPG_1_OPTS=--armor --recipient Ian_1 --encrypt --sign --local-user sample@domain.com --batch --passphrase-fd 0 set GPG_2_OPTS=--armor --recipient Ian_2 --encrypt --sign --local-user sample@domain.com --batch --passphrase-fd 0
REM *** Use simple program to split out the private key for GPG encryption. vanitygen 1 | x.exe | gpg %GPG_1_OPTS% | x.exe 2 | gpg %GPG_2_OPTS% >y copy /Y x + y z >nul type z&del x y
REM *** Now rename the output file to the bitcoin address. type z | find "Address: " > z.bat cscript findrep.vbs z.bat "Address: " "ren z " >nul call z.bat del z.bat
endlocal
|
|
|
|
CIYAM (OP)
Legendary
Offline
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
|
|
October 14, 2012, 06:51:04 AM |
|
Well I decided to whip up a bash script anyway as I think I will be using this with a Linux OS down the track. (note that as the x.cpp program actually creates the file 'x' I renamed x.cpp to w.cpp for Linux and compiled it using 'g++ -o w w.cpp') [genaddr] gpg_1_opts="--armor --recipient Ian_1 --encrypt --sign --local-user sample@domain.com --batch --passphrase-fd 0" gpg_2_opts="--armor --recipient Ian_2 --encrypt --sign --local-user sample@domain.com --batch --passphrase-fd 0"
# Use simple program to split out the private key for GPG encryption. ./vanitygen 1 | ./w | gpg $gpg_1_opts | ./w 2 | gpg $gpg_2_opts >y cat x y >z rm x y
cat z
# Now rename the output file to the bitcoin address. cat z | grep Address > z.sh sed -i 's/Address: /mv z /g' z.sh chmod a+x z.sh
./z.sh rm z.sh
Enjoy!
|
|
|
|
salfter
|
|
October 16, 2012, 03:57:24 PM Last edit: October 17, 2012, 06:32:49 PM by salfter |
|
Awesome. Been wanting this exact tool for some time.
Any chance of porting it to linux?
Not much to it as a shell script...knocked this together in Cygwin, but it'd work the same under Linux, Mac OS X, or whatever. Output is in the same format as produced here, but there's nothing to compile: #!/bin/bash out=$(vanitygen 1 2>/dev/null | grep -v Pattern | tr "\n" " ") addr=$(echo $out | sed "s/ Privkey.*//;s/Address: //") key=$(echo $out | sed "s/.* Privkey: //") (echo Address: $addr; \ echo ""; \ (echo <passphrase>; echo $key) | gpg2 --armor --recipient <dest-id> --encrypt --sign --local-user <src-sign-id> --batch --passphrase-fd 0 )>$addr.asc
The address and encrypted private key are written to a file; leave out ">$addr.asc" on the last line if you'd rather have it go to stdout. Substitute appropriate values as follows: <dest-id>: address or PGP key ID for whom the private key should be encrypted <src-sign-id>: address or PGP key ID for whom the private key should be signed <passphrase>: passphrase for <src-sign-id>
|
|
|
|
salfter
|
|
October 16, 2012, 06:05:17 PM Last edit: October 17, 2012, 06:33:00 PM by salfter |
|
#!/bin/bash out=$(vanitygen 1 2>/dev/null | grep -v Pattern | tr "\n" " ") addr=$(echo $out | sed "s/ Privkey.*//;s/Address: //") key=$(echo $out | sed "s/.* Privkey: //") (echo Address: $addr; \ echo ""; \ (echo <passphrase>; echo $key) | gpg2 --armor --recipient <dest-id> --encrypt --sign --local-user <src-sign-id> --batch --passphrase-fd 0 )>$addr.asc
...and to generate QR codes, add these to the preceding script: qrcode -o $addr.png -l M $addr (echo <passphrase>; qrcode -o - -l M $key) | gpg2 --armor --recipient <dest-id> --encrypt --sign --local-user <src-sign-id> --batch --passphrase-fd 0 >$addr-privkey.png.asc
qrcode is provided by libqrencode; a Win32 port is available. Note that the private key QR code is also encrypted.
|
|
|
|
CIYAM (OP)
Legendary
Offline
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
|
|
October 17, 2012, 02:25:33 AM |
|
Thanks for the neat bash script (I figured the program I whipped up shouldn't be needed for Linux but having worked for so many years under a standard Windows environment I have become accustomed to writing small programs to do such things).
I assume to do the 2-factor implementation you would assign a variable to the output of the first gpg call and then feed the password plus this into the second call?
|
|
|
|
salfter
|
|
October 17, 2012, 06:32:10 PM |
|
Thanks for the neat bash script (I figured the program I whipped up shouldn't be needed for Linux but having worked for so many years under a standard Windows environment I have become accustomed to writing small programs to do such things).
I assume to do the 2-factor implementation you would assign a variable to the output of the first gpg call and then feed the password plus this into the second call?
The original version of the script makes only one call to GPG. It's fed two lines: the passphrase of the signing key and the Bitcoin private key. The output from GPG is appended to the address and written to disk. In the version that generates QR codes, the second call gets the passphrase and a generated PNG with the QR code of the private key. This way, the private key (whether as text or a QR code) never goes to disk in unencrypted form. A QR code is also generated for the address; this is written to disk unencrypted.
|
|
|
|
CIYAM (OP)
Legendary
Offline
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
|
|
October 18, 2012, 03:09:53 AM |
|
I really like the QR code idea a lot - am not sure if most GPG public keys are small enough to fit into a QR code but if so then I think that the combination of vanitygen and GPG could provide an extremely secure (and indeed "air gapped") method to generate wallet addresses.
|
|
|
|
K1773R
Legendary
Offline
Activity: 1792
Merit: 1008
/dev/null
|
|
October 18, 2012, 06:25:25 AM |
|
Anyway for anyone that is interested I've whipped up a little utility and a couple of scripts to accomplish this (for Windows). Assuming you have GPG installed (with your public key in its keyring) create a dummy key-pair (I've used sample@domain.com here) and give it the password "password". First part is a simple tool (probably could just be a shell script in Linux) which firstly sends a hard-coded password to cout (the security of the GPG "from" should be irrelevant as it being used as a "send only" address) followed by the private key line it finds from cin (it is expecting its cin to be coming from "vanitygen"). The "address" line is output to a fixed filename ("x" in this source). [x.cpp]
#include <string> #include <fstream> #include <iostream>
const char* const c_outfile = "x"; const char* const c_password = "password";
const char* const c_address_prefix = "Address: "; const char* const c_privkey_prefix = "Privkey: ";
using namespace std;
int main( ) { ofstream outf( c_outfile );
cout << c_password << endl;
string str, addr, privkey; while( getline( cin, str ) ) { if( str.find( c_address_prefix ) == 0 ) outf << str << '\n' << endl; else if( str.find( c_privkey_prefix ) == 0 ) cout << str << endl; } }
The second part is a batch file you call in order to create a new bitcoin address (change Ian to your own GPG name): @echo off
REM *** Use simple program to split out the private key for GPG encryption. vanitygen 1 | x.exe | gpg --armor --recipient Ian --encrypt --sign --local-user sample@domain.com --batch --passphrase-fd 0 >y copy /Y x + y z >nul type z&del x y
REM *** Now rename the output file to the bitcoin address. type z | find "Address: " > z.bat cscript findrep.vbs z.bat "Address: " "ren z " >nul call z.bat del z.bat
The final part is the "findrep.vbs" tool (wouldn't be needed if using Linux): Const ForReading = 1 Const ForWriting = 2
If Wscript.Arguments.Count > 2 Then
strFileName = Wscript.Arguments(0) strOldText = Wscript.Arguments(1) strNewText = Wscript.Arguments(2)
Set objFSO = CreateObject("Scripting.FileSystemObject") Set objFile = objFSO.OpenTextFile(strFileName, ForReading)
strText = objFile.ReadAll objFile.Close strNewText = Replace(strText, strOldText, strNewText)
Set objFile = objFSO.OpenTextFile(strFileName, ForWriting) objFile.WriteLine strNewText objFile.Close
Else Wscript.Echo "Usage: findrep <file> <findstr> <replace>" Wscript.Quit End If
So now to generate a new bitcoin address you just type "genaddr" at the command prompt. As well as displaying the address and the GPG encrypted private key it saves the output to a file which is the name of the address (which can be safely backed up anywhere). The following a sample of the output: Address: 16vKwvg61UycrbhygXokVNQE3CxMSx22r7
-----BEGIN PGP MESSAGE----- Version: GnuPG v1.4.9 (MingW32)
hQEMA1cEJ0zSVDDtAQgAnagg9KrfhOlyZrSrItrQxB0IuoOnR8GmG0m4dXFYMCtY 2g4b1HEBhQ/xytGW+lon2LyRZpCoW5BAglW+NeFJ5Oev2c3XcBpVIDlwl9C4CsUJ w7/dUzFzqwfyiyDl662Bq8rF0qzOyQoyaj629Wz2EeBslb7yVejkg6mylc6hiPZz zTMxr4Qz4GByty5Qx1Z5X78h49zzeZHnm+22PoiP/5CjEZgX8LohIhyrmJnTRHDJ 47/nRE8j3w45/ozj73KVMyQ936IoxvhpiaoMwTp3UQ8cxdU4xaJBz6MOnjFJn5DV G3/Td4YpvJuYtNRNOg9xRT5lq2x0/71mYxN+4hoItNLACwFJyFrjitExf6du3Xyy CvT+kclF73xFGcAA+OLqbbeF1wRqqMxWrYPy2fAORua2B/iWPZgIkLNcCfLFZtL4 pABGG5DV0D+Dh+kyvDf03l2iFe3v1aedUKJ4UFnrBa7me/cQcZSnl5xknNBZD1PY R5IY1rrBC6BJ+6DtffRREwlp3tLgECpVL/zSBUGqWx68tzOxSnuwubCd0Q1z61fq L1wfDfjat052eB0xqM7x335LUvBbAKQJ5XxEaJ56CsJsQP4oU9EXcXZrvg2I =A3f1 -----END PGP MESSAGE-----
When you decide to "redeem" the address simply use "gpg --decode" with the file to get the private key: gpg: encrypted with 2048-bit RSA key, ID D25430ED, created 2012-03-25 "Ian Knowles <ian@ciyam.com>" Privkey: 5K6X8kvffAUYewAnmAuGHLB4wAk4UH2aZ1NBHdBf2YyzkUqzqHH gpg: Signature made 10/13/12 12:08:32 using DSA key ID 8C155FBD gpg: Good signature from "Sample <sample@domain.com>"
why not making a fifo (mkfifo) and then point vanitygen to that file? cat the fifo per pipe into gpg and there u go, basic linux stuff
|
[GPG Public Key]BTC/DVC/TRC/FRC: 1 K1773RbXRZVRQSSXe9N6N2MUFERvrdu6y ANC/XPM A K1773RTmRKtvbKBCrUu95UQg5iegrqyeA NMC: N K1773Rzv8b4ugmCgX789PbjewA9fL9Dy1 LTC: L Ki773RBuPepQH8E6Zb1ponoCvgbU7hHmd EMC: E K1773RxUes1HX1YAGMZ1xVYBBRUCqfDoF BQC: b K1773R1APJz4yTgRkmdKQhjhiMyQpJgfN
|
|
|
CIYAM (OP)
Legendary
Offline
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
|
|
October 18, 2012, 06:32:02 AM |
|
Anyway for anyone that is interested I've whipped up a little utility and a couple of scripts to accomplish this (for Windows).
why not making a fifo (mkfifo) and then point vanitygen to that file? cat the fifo per pipe into gpg and there u go, basic linux stuff Perhaps you missed that.
|
|
|
|
K1773R
Legendary
Offline
Activity: 1792
Merit: 1008
/dev/null
|
|
October 18, 2012, 07:08:21 AM |
|
Anyway for anyone that is interested I've whipped up a little utility and a couple of scripts to accomplish this (for Windows).
why not making a fifo (mkfifo) and then point vanitygen to that file? cat the fifo per pipe into gpg and there u go, basic linux stuff Perhaps you missed that. yea i did, sry 4 that ^^ altough note dont think its rock solid
|
[GPG Public Key]BTC/DVC/TRC/FRC: 1 K1773RbXRZVRQSSXe9N6N2MUFERvrdu6y ANC/XPM A K1773RTmRKtvbKBCrUu95UQg5iegrqyeA NMC: N K1773Rzv8b4ugmCgX789PbjewA9fL9Dy1 LTC: L Ki773RBuPepQH8E6Zb1ponoCvgbU7hHmd EMC: E K1773RxUes1HX1YAGMZ1xVYBBRUCqfDoF BQC: b K1773R1APJz4yTgRkmdKQhjhiMyQpJgfN
|
|
|
CIYAM (OP)
Legendary
Offline
Activity: 1890
Merit: 1086
Ian Knowles - CIYAM Lead Developer
|
|
October 18, 2012, 07:35:04 AM |
|
altough note dont think its rock solid I think it can be made rock solid but only if the computer you run it on is never again connected to the internet (or any network or other computer just in case it was in any way compromised). Another poster mentioned about creating QR codes which would make it convenient to transfer the encrypted private keys with an "air gap" (so there is no need to even use a USB to transfer the encrypted private keys for backup purposes).
|
|
|
|
K1773R
Legendary
Offline
Activity: 1792
Merit: 1008
/dev/null
|
|
October 18, 2012, 08:12:18 AM |
|
lastly would be a better solutions, there are to many viruses/trojans/similiar that are spreading over USB and even infect offline pcs, afterwards transfering data from the offline PC to a online PC and to a CC of a botnet/similiar. most ppl believe a offline PC is secure, but it isnt.
the idea with the QR Code would be more secure but not 100%, it would be 100% if the QR Software on the smartphone is rock solid too (no possible exploits) and other devices if they get integrated.
greetings
|
[GPG Public Key]BTC/DVC/TRC/FRC: 1 K1773RbXRZVRQSSXe9N6N2MUFERvrdu6y ANC/XPM A K1773RTmRKtvbKBCrUu95UQg5iegrqyeA NMC: N K1773Rzv8b4ugmCgX789PbjewA9fL9Dy1 LTC: L Ki773RBuPepQH8E6Zb1ponoCvgbU7hHmd EMC: E K1773RxUes1HX1YAGMZ1xVYBBRUCqfDoF BQC: b K1773R1APJz4yTgRkmdKQhjhiMyQpJgfN
|
|
|
|