document.write("
/* Code works but is NOT FORMALLY UNIT TESTED and should be treated as proof of concept only - i.e. don't use for amounts exceeding $10.00 until you have conducted your own testing. */ package main import ( "bufio" "bytes" "crypto/aes" "crypto/cipher" "crypto/rand" "crypto/sha256" "encoding/base64" "encoding/json" "fmt" "io" "io/ioutil" "log" "net/http" "os" "strings" "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcutil/base58" "golang.org/x/crypto/ripemd160" "golang.org/x/crypto/scrypt" ) var ( userData, _ = ioutil.ReadFile("seed") ) func main() { FileOps() } func InputPass() (passwordB []byte) { fmt.Print("Enter password: ") reader := bufio.NewReader(os.Stdin) input, err := reader.ReadString('\\n') if err != nil { fmt.Println("An error occured while reading input. Please try again", err) } password := strings.TrimSuffix(input, "\\n") passwordB = []byte(password) return passwordB } func InputMode() (modeB []byte) { fmt.Print("Enter mode choice [e/c]: press e key to create an encrypted AES file, press c key to decrypt an existing AES and use it to create a private key:") reader := bufio.NewReader(os.Stdin) input, err := reader.ReadString('\\n') if err != nil { fmt.Println("An error occured while reading input. Please try again", err) return } mode := strings.TrimSuffix(input, "\\n") modeB = []byte(mode) return modeB } func EncryptSeed(key, file []byte) ([]byte, error) { key, salt, err := DeriveKey(key, nil) if err != nil { return nil, err } blockCipher, err := aes.NewCipher(key) if err != nil { return nil, err } gcm, err := cipher.NewGCM(blockCipher) if err != nil { return nil, err } nonce := make([]byte, gcm.NonceSize()) if _, err = rand.Read(nonce); err != nil { return nil, err } ciphertext := gcm.Seal(nonce, nonce, file, nil) ciphertext = append(ciphertext, salt...) return ciphertext, nil } func DecryptSeed(key, file []byte) ([]byte, error) { salt, file := file[len(file)-32:], file[:len(file)-32] key, _, err := DeriveKey(key, salt) if err != nil { return nil, err } blockCipher, err := aes.NewCipher(key) if err != nil { return nil, err } gcm, err := cipher.NewGCM(blockCipher) if err != nil { return nil, err } nonce, ciphertext := file[:gcm.NonceSize()], file[gcm.NonceSize():] plaintext, err := gcm.Open(nil, nonce, ciphertext, nil) if err != nil { return nil, err } return plaintext, nil } func DeriveKey(password, salt []byte) ([]byte, []byte, error) { if salt == nil { salt = make([]byte, 32) if _, err := rand.Read(salt); err != nil { return nil, nil, err } } key, err := scrypt.Key(password, salt, 1048576, 8, 1, 32) if err != nil { return nil, nil, err } return key, salt, nil } func FileOps() []byte { var ret []byte mode := string(InputMode()) strMode := string(mode) if strMode == "e" { password := InputPass() ciphertext, err := EncryptSeed(password, userData) if err != nil { log.Fatal(err) } f, err := os.Create("a_aes.txt") if err != nil { panic(err.Error()) } _, err = io.Copy(f, bytes.NewReader(ciphertext)) if err != nil { panic(err.Error()) } os.Remove("seed") return ret } if strMode == "c" { password := InputPass() ciphertext2, err := ioutil.ReadFile("a_aes.txt") if err != nil { panic(err.Error()) } plaintext, err := DecryptSeed(password, ciphertext2) if err != nil { log.Fatal(err) } WalletOps(plaintext) return plaintext } if strMode != "c" && strMode != "e" { fmt.Println("Please try again and enter e or c.") return ret } return ret } func WalletOps(fromAES []byte) { qrng := GetQrng() aesFileInfo := string(fromAES) bAesFileInfo := []byte(aesFileInfo + qrng) hash := sha256.Sum256(bAesFileInfo) stretchedKey := StretchKey(255, hash, qrng) _, pub := btcec.PrivKeyFromBytes(btcec.S256(), stretchedKey[:]) fmt.Println("") fmt.Println("====") fmt.Println("Wallet Address:", WalletAddressB58(pub.SerializeUncompressed())) fmt.Println("====") fmt.Println("") fmt.Println("====") fmt.Println("Wallet WIF:", WalletWifB58(stretchedKey[:])) fmt.Println("====") fmt.Println("") } func GetQrng() (string) { resp, err := http.Get("https://qrng.anu.edu.au/API/jsonI.php?length=32&type=uint8") if err != nil { log.Fatalln(err) } body, err := ioutil.ReadAll(resp.Body) if err != nil { log.Fatalln(err) } if resp.StatusCode != 200 { log.Fatalln("None 200 status code returned, please try again") } type Data []uint8 type JsonData struct { Data Data } var data JsonData e := json.Unmarshal(body, &data) if e != nil { fmt.Println("JSON error occurred") } strEnc := base64.StdEncoding.EncodeToString(data.Data[:]) sha := sha256.Sum256([]byte(strEnc)) base64str := base64.StdEncoding.EncodeToString(sha[:]) return base64str } func StretchKey(iter int, hash [32]byte, qrng string) ([32]byte) { j := 0 for j < iter { base64str := base64.StdEncoding.EncodeToString(hash[:]) new := base64str + qrng newHash := sha256.Sum256([]byte(new)) hash = newHash j++ } return hash } func ShaRipe(b []byte) []byte { s := sha256.Sum256(b) r := ripemd160.New() r.Write(s[:]) return r.Sum([]byte{}) } func ShaSha(b []byte) []byte { x := sha256.Sum256(b) y := sha256.Sum256(x[:]) return y[:] } func WalletAddress(pubkey []byte) []byte { if len(pubkey) == 64 { pubkey = append([]byte{4}, pubkey...) } hash := ShaRipe(pubkey) hash = append([]byte{0}, hash...) checksum := ShaSha(hash) return append(hash, checksum[0:4]...) } func WalletAddressB58(pubkey []byte) string { return base58.Encode(WalletAddress(pubkey)) } func WalletWif(privkey []byte) []byte { bytes := append([]byte{0x80}, privkey...) checksum := ShaSha(bytes) return append(bytes, checksum[0:4]...) } func WalletWifB58(privkey []byte) string { return base58.Encode(WalletWif(privkey)) }