Skip to content

Commit

Permalink
v0.1.0; 2023-08-22.1100
Browse files Browse the repository at this point in the history
  • Loading branch information
cyclone-github authored Aug 22, 2023
1 parent b330784 commit c385a14
Show file tree
Hide file tree
Showing 18 changed files with 1,046 additions and 3 deletions.
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# Cyclone's Hashes.com API Escrow Tool
(coming soon)

![image](https://i.imgur.com/gNpMGaq.png)

Expand All @@ -17,12 +16,12 @@ https://github.com/PlumLulz/hashes.com-cli
- Paste custom file path
- Paste hash:plaintext
- Show Upload History
- Search Hashes
- Search Hashes (requires credits from hashes.com)
- Hash Identifier
- Wallet Balance
- Show Profit
- Withdraw History
- Saves API key locally with AES encrypted key file

###Compile from source code info:
### Compile from source code info:
- https://github.com/cyclone-github/scripts/blob/main/intro_to_go.txt
113 changes: 113 additions & 0 deletions src/api_key.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package main

import (
"crypto/aes"
"crypto/cipher"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
"net"
"net/http"
)

// generate unique encryption key
func getEncryptionKey() {
decodedSeed, err := base64.StdEncoding.DecodeString(base64StaticSeedKey)
if err != nil {
fmt.Printf("Error decoding Base64 static seed key: %v\n")
return
}

staticSeedKey := string(decodedSeed)

interfaces, err := net.Interfaces()
if err != nil || len(interfaces) == 0 {
hash := sha256.Sum256([]byte(staticSeedKey))
encryptionKey = hex.EncodeToString(hash[:])
return
}

var macAddr string
for _, i := range interfaces {
if i.HardwareAddr != nil && len(i.HardwareAddr.String()) > 0 {
macAddr = i.HardwareAddr.String()
break
}
}

seed := macAddr + staticSeedKey
hash := sha256.Sum256([]byte(seed))
encryptionKey = hex.EncodeToString(hash[:])
}

// encrypt key file
func encrypt(data []byte, passphrase string) ([]byte, error) {
block, err := aes.NewCipher(getSHA256Hash(passphrase))
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
nonce := make([]byte, gcm.NonceSize())
ciphertext := gcm.Seal(nonce, nonce, data, nil)
return ciphertext, nil
}

// decrypt key file
func decrypt(data []byte, passphrase string) ([]byte, error) {
key := getSHA256Hash(passphrase)
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
nonceSize := gcm.NonceSize()
nonce, ciphertext := data[:nonceSize], data[nonceSize:]
plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
if err != nil {
return nil, err
}
return plaintext, nil
}

// sha256Hash function for encrypt /decrypt file func
func getSHA256Hash(text string) []byte {
hash := sha256.Sum256([]byte(text))
return hash[:]
}

// verify hashes.com API key
func verifyAPIKey(apiKey string) bool {
url := fmt.Sprintf("https://hashes.com/en/api/balance?key=%s", apiKey)

resp, err := http.Get(url)
if err != nil {
fmt.Printf("Failed to send request: %v\n", err)
return false
}
defer resp.Body.Close()

var response struct {
Success bool `json:"success"`
}
err = json.NewDecoder(resp.Body).Decode(&response)
if err != nil {
fmt.Printf("Failed to decode response: %v\n", err)
return false
}

if response.Success {
fmt.Println("API key verified")
return true
}

//fmt.Println("API key not verified, try again")
return false
}
21 changes: 21 additions & 0 deletions src/clear_screen.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package main

import (
"os"
"os/exec"
"runtime"
)

// clear screen function
func clearScreen() {
switch runtime.GOOS {
case "linux", "darwin":
cmd := exec.Command("clear")
cmd.Stdout = os.Stdout
cmd.Run()
case "windows":
cmd := exec.Command("cmd", "/c", "cls")
cmd.Stdout = os.Stdout
cmd.Run()
}
}
67 changes: 67 additions & 0 deletions src/found_history.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package main

import (
"encoding/json"
"fmt"
"net/http"
"os"
"text/tabwriter"
)

// case 2, get found history
func getFoundHistory(apiKey string) error {
url := fmt.Sprintf("https://hashes.com/en/api/uploads?key=%s", apiKey)

resp, err := http.Get(url)
if err != nil {
return fmt.Errorf("failed to send request: %v", err)
}
defer resp.Body.Close()

var response struct {
Success bool `json:"success"`
List []FoundHistory `json:"list"`
}
err = json.NewDecoder(resp.Body).Decode(&response)
if err != nil {
return fmt.Errorf("failed to decode response: %v", err)
}

if !response.Success {
return fmt.Errorf("request was not successful")
}

fmt.Println("Upload History (last 10):\n")
writer := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', tabwriter.AlignRight|tabwriter.Debug)
defer writer.Flush()

fmt.Fprintln(writer, "ID\tDate\tBTC (USD)\tXMR (USD)\tLTC (USD)\tAlgo\t-m\tFound\tTotal\tStatus")

btcRate, _ := toUSD(1, "BTC")
xmrRate, _ := toUSD(1, "XMR")
ltcRate, _ := toUSD(1, "LTC")

startIndex := len(response.List) - 10
if startIndex < 0 {
startIndex = 0
}

for i := startIndex; i < len(response.List); i++ {
history := response.List[i]

btc := parseFloat(history.BTC)
xmr := parseFloat(history.XMR)
ltc := parseFloat(history.LTC)

btcUSD := fmt.Sprintf("$%.3f", btc*parseFloat(btcRate["currentprice"].(string)))
xmrUSD := fmt.Sprintf("$%.3f", xmr*parseFloat(xmrRate["currentprice"].(string)))
ltcUSD := fmt.Sprintf("$%.3f", ltc*parseFloat(ltcRate["currentprice"].(string)))

fmt.Fprintf(writer, "%d\t%s\t%s\t%s\t%s\t%s\t%d\t%d\t%d\t%s\n",
history.ID, history.Date,
btcUSD, xmrUSD, ltcUSD,
history.Algorithm, history.AlgorithmID, history.ValidHashes, history.TotalHashes, history.Status)
}

return nil
}
74 changes: 74 additions & 0 deletions src/get_api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package main

import (
"fmt"
"io/ioutil"
"os"
"time"
)

// case 8, get new API key
func getAPIKey(promptForNewKey bool) string {
if promptForNewKey {
clearScreen()
for {
fmt.Println("Enter your API key from hashes.com/profile")
var newAPIKey string
fmt.Scanln(&newAPIKey)

if verifyAPIKey(newAPIKey) {
encryptedKey, err := encrypt([]byte(newAPIKey), encryptionKey)
if err != nil {
fmt.Printf("Error encrypting API key: %v\n", err)
continue
}
err = ioutil.WriteFile(apiKeyFile, encryptedKey, 0644)
if err != nil {
fmt.Printf("Error writing encrypted API key to file: %v\n", err)
continue
}
return newAPIKey
} else {
fmt.Println("API key not verified, try again.")
time.Sleep(500 * time.Millisecond)
}
}
}

for {
var apiKey string

if _, err := os.Stat(apiKeyFile); err == nil {
encryptedKey, err := ioutil.ReadFile(apiKeyFile)
if err != nil {
fmt.Printf("Error reading API key file: %v\n", err)
} else {
decryptedKey, err := decrypt(encryptedKey, encryptionKey)
if err != nil {
fmt.Printf("Error decrypting API key: %v\n", err)
} else {
apiKey = string(decryptedKey)
if verifyAPIKey(apiKey) {
return apiKey
}
}
}
}

fmt.Println("Enter your API key from hashes.com/profile")
fmt.Scanln(&apiKey)
encryptedKey, err := encrypt([]byte(apiKey), encryptionKey)
if err != nil {
fmt.Printf("Error encrypting API key: %v\n", err)
continue
}
err = ioutil.WriteFile(apiKeyFile, encryptedKey, 0644)
if err != nil {
fmt.Printf("Error writing encrypted API key to file: %v\n", err)
continue
}
if verifyAPIKey(apiKey) {
return apiKey
}
}
}
31 changes: 31 additions & 0 deletions src/globals.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package main

// global structs, constants and variables
type FoundHistory struct {
ID int `json:"id"`
BTC string `json:"btc"`
XMR string `json:"xmr"`
LTC string `json:"ltc"`
Date string `json:"date"`
TotalHashes int `json:"totalHashes"`
ValidHashes int `json:"validHashes"`
Status string `json:"status"`
Algorithm string `json:"algorithm"`
AlgorithmID int `json:"algorithmId"`
}

type WalletBalances struct {
BTC string `json:"BTC"`
XMR string `json:"XMR"`
LTC string `json:"LTC"`
Credits string `json:"credits"`
}

const (
apiKeyFile = "api_key.enc"
base64StaticSeedKey = "NWl5cTk3RlEwZy9HODFBQTU3NF5lZU0lel0zSwo="
)

var (
encryptionKey string
)
3 changes: 3 additions & 0 deletions src/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module main.go

go 1.20
47 changes: 47 additions & 0 deletions src/hash_identifier.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package main

import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)

// case 4, hash identifier
func hashIdentifier(hash string, extended bool) error {
url := "https://hashes.com/en/api/identifier?hash=" + hash
if extended {
url += "&extended=true"
}

resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()

body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}

var result map[string]interface{}
if err := json.Unmarshal(body, &result); err != nil {
return err
}

if success, ok := result["success"].(bool); ok && success {
if algorithms, ok := result["algorithms"].([]interface{}); ok && len(algorithms) > 0 {
fmt.Println("Possible Algorithms:")
for _, algo := range algorithms {
fmt.Printf(" %s\n", algo)
}
} else {
fmt.Println("No algorithms found.")
}
} else {
fmt.Println("No results found.")
}

return nil
}
Loading

0 comments on commit c385a14

Please sign in to comment.