You are using a JavaScript library to do this, which will result in terrible performance.
You are much better off using a native library. For instance, in NodeJS you can do the following:
const { createHash } = require('crypto');
function sha256inb64(value) {
const hash = createHash('sha256');
hash.update(value);
return hash.digest('base64');
}
I've deliberately kept the name short. This returns the digest directly as base 64 which is much faster to encode and doesn't limit the output size.
You can limit the number of output characters to 8 by using hash.digest('base64').substring(0, 8)
in the code provided on top.
Note that this only provides (8 / 4) * 3 = 6 bytes or 48 bits of security, so it is not considered cryptographically secure anymore, rendering the SHA256 function next to useless.
If you don't need cryptographic security then there are a lot faster hashes available, see e.g. a comparison of hashes here.
function stringToInt(string) {
What does this even mean? What does it mean for a string to be put into an integer? Will it create an integer of any particular size? It doesn't constrain the input string
for certain.
Otherwise the base conversion seems to be reasonable.
int = Math.floor(int / base);
This is definitely restricting the input size.
function intToString(int) {
Same problem with the naming, although it at least seems to be the reverse operation of stringToInt
.
function sha_256(value) {
This name is a terrible name for this particular function. You're using a sha256
that - for some bad reason - always returns hexadecimals. Now by adding an underscore it suddenly returns the a value after "compression" in a different text encoding? It isn't explained why, why it is useful or that it is "compressed" as claimed.
let bits = hexToBytes(sha256(value) /* returns a hex string */ )
Wait, what? Does it return bits, bytes or hexadecimals? You are aware that those are different concepts, right? It returns bytes as indicated.
for (let i = 0; i < bits.length; i += 8) {
const a = bits[i];
const b = bits[i + 1];
const c = bits[i + 2];
const d = bits[i + 3];
const e = bits[i + 4];
const f = bits[i + 5];
const g = bits[i + 6];
const h = bits[i + 7];
const chunk = intToString(a + b + c + d + e + f + g + h);
str += chunk.padStart(2, '0');
}
Note I've used the correct but rolled back code of the question here, as the original code doesn't make any sense by itself. That edit should not have been rolled back.
If you're doing the counting instead of the computer then you're probably doing something wrong. You can add up to a total using an inner for
loop.
Worse is that adding values is really dangerous when it comes to "compression"; it is of course clear that 1 + 2
will add up to the same value as 2 + 1
. If you do that with a lot of values then it will allow an attacker to quickly find collisions. Just taking the first characters is likely more secure - and it cannot be less secure.
main
. I occasionally complain that author should have offered some combination of (1) example {in,out}put, (2) same thing in unit test form, (3) coverage measurement, (4) algorithm citation, (5) specification. The first two are amenable to automated process improvements in how new questions are accepted. \$\endgroup\$