gpujs / gpu.js

GPU Accelerated JavaScript
https://gpu.rocks
MIT License
15.1k stars 652 forks source link

SHA256 Hashing #650

Open SpookyPool opened 3 years ago

SpookyPool commented 3 years ago

Hello people,

I was wondering if it's possible to do SH256 hashing with GPU.JS. If so, how would I approach this?

Thanks in advance.

harshkhandeparkar commented 3 years ago

I think accelerating a single hash won't be possible or if possible, not practical. But multiple hashes can be done in parallel, provided that you have the algorithm (written in js) for a single hash.

SpookyPool commented 3 years ago

I'm working on that writing the SHA256 algo as we speak. Running it in parallel you mean with

.setOutput([100,100]);

for example?

harshkhandeparkar commented 3 years ago

setOutput([100, 100]) means that the output is going to be a 100x100 array where each element in the array is going to be computed in parallel, on an independent thread on the gpu.

SpookyPool commented 3 years ago

My goal is to make a SHA256 hasher that will add a nonce. How could I add that nonce on every new thread? I'm really new to this GPU stuff

harshkhandeparkar commented 3 years ago

Just like I am new to SHA lol

SpookyPool commented 3 years ago

This is pulling out my hairs... It's amazing that something like this exist. But figuring this out as a noob is terrible

robertleeplummerjr commented 3 years ago

Figuring something like this as an expert is terrible, lol.

SpookyPool commented 3 years ago

Wdym by that?

harshkhandeparkar commented 3 years ago

Is there a simpler version of your problem so that we can help you?

robertleeplummerjr commented 3 years ago

SHA256 is one of the more complex algorithms you'll be up against creating to run on a GPU.

harshkhandeparkar commented 3 years ago

Yup. I have tried to understand it a countless number of times with 0 success.

SpookyPool commented 3 years ago

Is there a simpler version of your problem so that we can help you?

Is it possible to run a calculation in the kernel and let a number (nonce) bump it up by 1 on every thread, for example. Thread 1 calculates something with nonce 0 and thread 2 calculates something with nonce 1 etc, etc,

SHA256 is one of the more complex algorithms you'll be up against creating to run on a GPU.

It is not easy indeed though. I found some javascript code to calculate SHA256 and got it almost working on the gpu.js library but I had some small issue with some operators like '|=' and lvalue.

harshkhandeparkar commented 3 years ago

Is it possible to run a calculation in the kernel and let a number (nonce) bump it up by 1 on every thread, for example. Thread 1 calculates something with nonce 0 and thread 2 calculates something with nonce 1 etc, etc,

If the threads are calculating something independently then yes. You can use the this.thread.x variable as nonce.

0xrgg commented 3 years ago

Did you get something working? I'm actually looking for something very similar and I keep getting an error with the function I'm trying based off my existing code.

It is not easy indeed though. I found some javascript code to calculate SHA256 and got it almost working on the gpu.js library but I had some small issue with some operators like '|=' and lvalue.

SpookyPool commented 3 years ago

Did you get something working? I'm actually looking for something very similar and I keep getting an error with the function I'm trying based off my existing code.

It is not easy indeed though. I found some javascript code to calculate SHA256 and got it almost working on the gpu.js library but I had some small issue with some operators like '|=' and lvalue.

No I did not. It is already very hard to do the calculation stuff with limited operators and limited Array ouputs. Also I don't know a few other things that is required for my project

0xrgg commented 3 years ago

No I did not. It is already very hard to do the calculation stuff with limited operators and limited Array ouputs. Also I don't know a few other things that is required for my project

Ah man that sucks, I was looking through the documentation and it suggests you can pass functions to it, so I assumed you could make an array and for each "this.thread.x" being your nonce compute the hash into this.thread.y.... I tried this myself and just ended up with errors, but I figured that was me just using it incorrectly and there are very few examples online of people not using the library to do graphical computations.

harshkhandeparkar commented 3 years ago

You can use just a 2D array with .setOutput(100 or 1000 or whatever) and then there will just be this.thread.x. You can return the hash. The output will have an array of all the hashes.

harshkhandeparkar commented 3 years ago

For operators that are not supported, you might have to implement them yourself using other ones.

0xrgg commented 3 years ago

@HarshKhandeparkar It's reassuring to know that what I want to do is possible, but I just can't figure it out. I've tried to methods so far:

Using a function with my variables declared to feed into the function and return the hash (with const kernel modified to use kernelFunction) function kernelFunction(index, lasthash, timestamp, data, nonce) { return SHA256(index + lasthash + timestamp + JSON.stringify(data) + nonce).toString(); }

Then I tried just doing it all inside createKernel, as is done on the Caesar cipher example.. const kernel = gpu.createKernel(function (index, lasthash, timestamp, data, nonce) { return SHA256(index, lasthash, timestamp, data, [this.thread.x]); }).setOutput(1024);

I get the following error with the above: const [width, height] = this.output;

TypeError: this.output is not iterable

I'm confused as to whether I need to generate an empty matrix first to populate with the hash or not (this isn't done in the Caesar cipher example)?

P.s: Apologies for hijacking the issue @SpookyPool

harshkhandeparkar commented 3 years ago

What is SHA256 and where is it defined?

harshkhandeparkar commented 3 years ago

NOTE: string outputs are not supported at all. Nor are strings supported inside kernels.

0xrgg commented 3 years ago

So SHA256 is just defined as a requre: const SHA256 = require('crypto-js/sha256');

Though I did not realise strings aren't supported, I suppose I'll have to play around with the JSON object and convert before feeding to the kernel then

SpookyPool commented 3 years ago

Could you guys add me onto discord?! So we can create a group and figure this out together?! Appeljuice#0420

SpookyPool commented 3 years ago

So SHA256 is just defined as a requre: const SHA256 = require('crypto-js/sha256');

Though I did not realise strings aren't supported, I suppose I'll have to play around with the JSON object and convert before feeding to the kernel then

I did got my sha256 generation almost working by coverting my string to bytes array and passing that into the sha256 inside the kernel and then do the magic. But he part of the whole magic is just way beyond my limits

harshkhandeparkar commented 3 years ago

External JS functions cannot be used on the GPU :(

harshkhandeparkar commented 3 years ago

Could you guys add me onto discord?! So we can create a group and figure this out together?! Appeljuice#0420

All of us can talk on gitter if you don't mind. I don't mind discord either but gitter already has a gpu.js community. https://gitter.im/gpujs/gpu.js

0xrgg commented 3 years ago

@HarshKhandeparkar Ahhh okay that makes sense - I just had a quick look through the sha256 script and it looks like it's calling multiple other libraries from Crypto (core, hmac256) so not sure it would be possible to just adapt that code into the same file as to avoid calling an external function. Can you think of any potential workarounds?

SpookyPool commented 3 years ago

Could you guys add me onto discord?! So we can create a group and figure this out together?! Appeljuice#0420

All of us can talk on gitter if you don't mind. I don't mind discord either but gitter already has a gpu.js community. https://gitter.im/gpujs/gpu.js

Gitter seems fine! I posted already there. U cannot use any external librarys in the kernel. You have to create your own because everything is done in numbers. I'm willing to take another shot on this sha256 stuff but I'm not sure if I will be able to get it working

0xrgg commented 3 years ago

@SpookyPool Did you rewrite from the original script? Seems like such a daunting task, but it's the last step in my project before I can 100% complete it so between two minds as to whether or not I leave with current functionality

Was just trying to speculate whether or not the calculation ran by my original function would be equal to that of the GPU kernel once deviating from the library - which might break my app altogether 😮

harshkhandeparkar commented 3 years ago

GPU.js transpiles javascript into GLSL(a much lower level language) under the hood. This compiled code is then run on the GPU. And it is a compiled language, in fact, it doesn't even support strings. Whatever you write as the kernel function will be first converted to a string and then compiled to GLSL, so whatever is defined inside the kernel function only will be transpiled. If you try to reference something undefined like the function SHA256 in your case, it will throw an error.

If at all you want external functions, you will either have to implement them yourself or transpile library function(if possible) directly. Useful: https://github.com/gpujs/gpu.js#adding-custom-functions

0xrgg commented 3 years ago

I did check out the documentation and looked at that part you mentioned which is why I assumed it would be a simple task to just add in my own function there, though it makes sense as to why that isn't possible. As much as I would like to get this working, I don't think I have the ability to transpile it or lift it from the library into the project file and still have it function correctly.. Looking through the core file and modules, things seem to be quite interlinked. I think I'll just have to skip this functionality out of my project but thanks for clearing things up :disappointed:

SpookyPool commented 3 years ago

I did check out the documentation and looked at that part you mentioned which is why I assumed it would be a simple task to just add in my own function there, though it makes sense as to why that isn't possible. As much as I would like to get this working, I don't think I have the ability to transpile it or lift it from the library into the project file and still have it function correctly.. Looking through the core file and modules, things seem to be quite interlinked. I think I'll just have to skip this functionality out of my project but thanks for clearing things up 😞

For now if you dont know how to do it, you have to wait u til someone will or when i finally done it. I know I probably can. But it requires A LOT of time for me...

May I ask what you're trying todo in your project?

benrayfield commented 2 years ago

Here's my implementation of sha256 in javascript. It doesnt call any libraries. If you moved part of the array to be a param, or just used consts, and replaced all int math with using the low bits of floats (you only get 24 int bits per float), you could probably port this to GPU.js: https://github.com/benrayfield/jsutils/blob/master/src/sha256.js