Initial commit.
This commit is contained in:
commit
0a9434be1b
18 changed files with 1860 additions and 0 deletions
87
client/README.md
Normal file
87
client/README.md
Normal file
|
@ -0,0 +1,87 @@
|
|||
# NOJSCAP client
|
||||
|
||||
The client directory includes NOJSCAP client implementations in multiple languages. Each version takes a challenge string and a difficulty level, then searches for a nonce such that the SHA-256 hash of `challenge + nonce` begins with the required number of leading zero bits.
|
||||
|
||||
## Implementations
|
||||
|
||||
- **C**: `nojscap.c`
|
||||
- **Go**: `nojscap.go`
|
||||
- **Python**: `nojscap.py`
|
||||
- **JavaScript (Node.js)**: `nojscap.js`
|
||||
- **Rust**: `nojscap.rs`
|
||||
|
||||
Each implementation provides similar usage and functionality.
|
||||
|
||||
---
|
||||
|
||||
## C Version
|
||||
|
||||
### Compilation
|
||||
|
||||
You need:
|
||||
|
||||
- GCC or any C compiler
|
||||
- OpenSSL development libraries (`libssl-dev` on Debian-based systems)
|
||||
|
||||
```sh
|
||||
gcc -O2 -o nojscap nojscap.c -lssl -lcrypto
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
```sh
|
||||
./nojscap <challenge_string> <difficulty_bits>
|
||||
```
|
||||
|
||||
- `challenge_string`: Any input string used as the challenge.
|
||||
- `difficulty_bits`: Integer between 1 and 256. Higher values are more computationally expensive.
|
||||
|
||||
### Example
|
||||
|
||||
```sh
|
||||
./nojscap libroot12 26
|
||||
Attempts: 0
|
||||
Attempts: 1048576
|
||||
Attempts: 2097152
|
||||
Attempts: 3145728
|
||||
Attempts: 4194304
|
||||
Attempts: 5242880
|
||||
Attempts: 6291456
|
||||
Found nonce: 6368109
|
||||
Hash: 0000000e724d990815e84e8a53f3f2410875046fe62a050de830d706b853ebe2
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Python
|
||||
|
||||
```sh
|
||||
python3 nojscap.py <challenge_string> <difficulty_bits>
|
||||
```
|
||||
|
||||
May require the `hashlib` module if using older Python verisons (standard in Python 3).
|
||||
|
||||
## Go
|
||||
|
||||
```sh
|
||||
go run nojscap.go <challenge_string> <difficulty_bits>
|
||||
```
|
||||
|
||||
Requires Go 1.13+.
|
||||
|
||||
## JavaScript (Node.js)
|
||||
|
||||
```sh
|
||||
node nojscap.js <challenge_string> <difficulty_bits>
|
||||
```
|
||||
|
||||
Uses the built-in `crypto` module.
|
||||
|
||||
## Rust
|
||||
|
||||
```sh
|
||||
rustc nojscap.rs -o nojscap_rs
|
||||
./nojscap_rs <challenge_string> <difficulty_bits>
|
||||
```
|
||||
|
||||
Requires Rust and `sha2` crate if using the `Cargo` version.
|
71
client/nojscap.c
Normal file
71
client/nojscap.c
Normal file
|
@ -0,0 +1,71 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
int check_difficulty(const unsigned char *hash, int difficulty_bits) {
|
||||
int bits = difficulty_bits;
|
||||
int i = 0;
|
||||
while (bits > 0) {
|
||||
unsigned char byte = hash[i];
|
||||
if (bits >= 8) {
|
||||
if (byte != 0) return 0;
|
||||
bits -= 8;
|
||||
} else {
|
||||
unsigned char mask = 0xFF << (8 - bits);
|
||||
if ((byte & mask) != 0) return 0;
|
||||
bits = 0;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "Usage: %s <challenge_string> <difficulty_bits>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *challenge = argv[1];
|
||||
int difficulty_bits = atoi(argv[2]);
|
||||
if (difficulty_bits <= 0 || difficulty_bits > 256) {
|
||||
fprintf(stderr, "Difficulty bits must be between 1 and 256\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned char hash[SHA256_DIGEST_LENGTH];
|
||||
unsigned long long counter = 0;
|
||||
|
||||
size_t challenge_len = strlen(challenge);
|
||||
char *input = malloc(challenge_len + 32);
|
||||
|
||||
if (!input) {
|
||||
fprintf(stderr, "Memory allocation failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
sprintf(input, "%s%llu", challenge, counter);
|
||||
SHA256((unsigned char *)input, strlen(input), hash);
|
||||
|
||||
if (check_difficulty(hash, difficulty_bits)) {
|
||||
printf("===================\n");
|
||||
printf("Found nonce: %llu\n", counter);
|
||||
printf("===================\n");
|
||||
printf("Hash: ");
|
||||
for (int i = 0; i < SHA256_DIGEST_LENGTH; i++)
|
||||
printf("%02x", hash[i]);
|
||||
printf("\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if ((counter & 0xFFFFF) == 0) {
|
||||
printf("Attempts: %llu\n", counter);
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
|
||||
free(input);
|
||||
return 0;
|
||||
}
|
66
client/nojscap.go
Normal file
66
client/nojscap.go
Normal file
|
@ -0,0 +1,66 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func checkDifficulty(hash []byte, difficultyBits int) bool {
|
||||
bits := difficultyBits
|
||||
i := 0
|
||||
for bits > 0 {
|
||||
b := hash[i]
|
||||
if bits >= 8 {
|
||||
if b != 0 {
|
||||
return false
|
||||
}
|
||||
bits -= 8
|
||||
} else {
|
||||
mask := byte(0xFF << (8 - bits))
|
||||
if (b & mask) != 0 {
|
||||
return false
|
||||
}
|
||||
bits = 0
|
||||
}
|
||||
i++
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) != 3 {
|
||||
fmt.Fprintf(os.Stderr, "Usage: %s <challenge_string> <difficulty_bits>\n", os.Args[0])
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
challenge := os.Args[1]
|
||||
difficultyBits, err := strconv.Atoi(os.Args[2])
|
||||
if err != nil || difficultyBits <= 0 || difficultyBits > 256 {
|
||||
fmt.Fprintln(os.Stderr, "Difficulty bits must be between 1 and 256")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var counter uint64 = 0
|
||||
|
||||
for {
|
||||
input := fmt.Sprintf("%s%d", challenge, counter)
|
||||
hash := sha256.Sum256([]byte(input))
|
||||
|
||||
if checkDifficulty(hash[:], difficultyBits) {
|
||||
fmt.Printf("===================\n")
|
||||
fmt.Printf("Found nonce: %d\n", counter)
|
||||
fmt.Printf("===================\n")
|
||||
fmt.Printf("Hash: %s\n", hex.EncodeToString(hash[:]))
|
||||
break
|
||||
}
|
||||
|
||||
if counter&0xFFFFF == 0 {
|
||||
fmt.Printf("Attempts: %d\n", counter)
|
||||
}
|
||||
|
||||
counter++
|
||||
}
|
||||
}
|
57
client/nojscap.js
Normal file
57
client/nojscap.js
Normal file
|
@ -0,0 +1,57 @@
|
|||
const crypto = require('crypto');
|
||||
|
||||
function checkDifficulty(hashBuffer, difficultyBits) {
|
||||
let bits = difficultyBits;
|
||||
let i = 0;
|
||||
while (bits > 0) {
|
||||
const byte = hashBuffer[i];
|
||||
if (bits >= 8) {
|
||||
if (byte !== 0) return false;
|
||||
bits -= 8;
|
||||
} else {
|
||||
const mask = 0xFF << (8 - bits);
|
||||
if ((byte & mask) !== 0) return false;
|
||||
bits = 0;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function main() {
|
||||
if (process.argv.length !== 4) {
|
||||
console.error(`Usage: node ${process.argv[1]} <challenge_string> <difficulty_bits>`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const challenge = process.argv[2];
|
||||
const difficultyBits = parseInt(process.argv[3], 10);
|
||||
|
||||
if (isNaN(difficultyBits) || difficultyBits <= 0 || difficultyBits > 256) {
|
||||
console.error('Difficulty bits must be a number between 1 and 256');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let counter = 0;
|
||||
|
||||
while (true) {
|
||||
const input = challenge + counter;
|
||||
const hash = crypto.createHash('sha256').update(input).digest();
|
||||
|
||||
if (checkDifficulty(hash, difficultyBits)) {
|
||||
console.log('===================');
|
||||
console.log(`Found nonce: ${counter}`);
|
||||
console.log('===================');
|
||||
console.log(`Hash: ${hash.toString('hex')}`);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((counter & 0xFFFFF) === 0) {
|
||||
console.log(`Attempts: ${counter}`);
|
||||
}
|
||||
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
52
client/nojscap.py
Normal file
52
client/nojscap.py
Normal file
|
@ -0,0 +1,52 @@
|
|||
import hashlib
|
||||
import sys
|
||||
|
||||
def check_difficulty(hash_bytes: bytes, difficulty_bits: int) -> bool:
|
||||
bits = difficulty_bits
|
||||
i = 0
|
||||
while bits > 0:
|
||||
byte = hash_bytes[i]
|
||||
if bits >= 8:
|
||||
if byte != 0:
|
||||
return False
|
||||
bits -= 8
|
||||
else:
|
||||
mask = 0xFF << (8 - bits) & 0xFF
|
||||
if (byte & mask) != 0:
|
||||
return False
|
||||
bits = 0
|
||||
i += 1
|
||||
return True
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 3:
|
||||
print(f"Usage: {sys.argv[0]} <challenge_string> <difficulty_bits>")
|
||||
sys.exit(1)
|
||||
|
||||
challenge = sys.argv[1]
|
||||
try:
|
||||
difficulty_bits = int(sys.argv[2])
|
||||
except ValueError:
|
||||
print("Difficulty must be a number")
|
||||
sys.exit(1)
|
||||
|
||||
if difficulty_bits <= 0 or difficulty_bits > 256:
|
||||
print("Difficulty bits must be between 1 and 256")
|
||||
sys.exit(1)
|
||||
|
||||
counter = 0
|
||||
while True:
|
||||
input_str = f"{challenge}{counter}"
|
||||
hash_bytes = hashlib.sha256(input_str.encode()).digest()
|
||||
if check_difficulty(hash_bytes, difficulty_bits):
|
||||
print("====================")
|
||||
print(f"Found nonce: {counter}")
|
||||
print("====================")
|
||||
print(f"Hash: {hash_bytes.hex()}")
|
||||
break
|
||||
if counter & 0xFFFFF == 0:
|
||||
print(f"Attempts: {counter}")
|
||||
counter += 1
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
65
client/nojscap.rs
Normal file
65
client/nojscap.rs
Normal file
|
@ -0,0 +1,65 @@
|
|||
use sha2::{Digest, Sha256};
|
||||
use std::env;
|
||||
use std::process;
|
||||
|
||||
fn check_difficulty(hash: &[u8], difficulty_bits: u32) -> bool {
|
||||
let mut bits = difficulty_bits;
|
||||
let mut i = 0;
|
||||
|
||||
while bits > 0 {
|
||||
let byte = hash[i];
|
||||
if bits >= 8 {
|
||||
if byte != 0 {
|
||||
return false;
|
||||
}
|
||||
bits -= 8;
|
||||
} else {
|
||||
let mask = 0xFF << (8 - bits);
|
||||
if (byte & mask) != 0 {
|
||||
return false;
|
||||
}
|
||||
bits = 0;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
||||
if args.len() != 3 {
|
||||
eprintln!("Usage: {} <challenge_string> <difficulty_bits>", args[0]);
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
let challenge = &args[1];
|
||||
let difficulty_bits: u32 = match args[2].parse() {
|
||||
Ok(num) if num > 0 && num <= 256 => num,
|
||||
_ => {
|
||||
eprintln!("Difficulty bits must be between 1 and 256");
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
let mut counter: u64 = 0;
|
||||
|
||||
loop {
|
||||
let input = format!("{}{}", challenge, counter);
|
||||
let hash = Sha256::digest(input.as_bytes());
|
||||
|
||||
if check_difficulty(&hash, difficulty_bits) {
|
||||
println!("===================");
|
||||
println!("Found nonce: {}", counter);
|
||||
println!("===================");
|
||||
println!("Hash: {:x}", hash);
|
||||
break;
|
||||
}
|
||||
|
||||
if counter & 0xFFFFF == 0 {
|
||||
println!("Attempts: {}", counter);
|
||||
}
|
||||
|
||||
counter += 1;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue