Hi,
Anyone knows how to encrypt a string variable to Sha1?
When encrypting to Base64 I use .toString(‘base64’), so wonder if there are anything similar available for Sha1 encryption?
Hope someone can guide me
Thx in advance
const crypto = (this.constructor.constructor('return process.mainModule.require')())('crypto');
function hash(string) {
const hasher = crypto.createHash('sha1');
hasher.update(string);
return hasher.digest('hex');
}
console.log( hash('hello world') )
Of course, SHA1 isn’t an encryption algorithm but a hash function (and Base64 is an encoding method)
It worked
First thank you - you saved my day.
Second thanks for super fast reply…
and third, you learned me something new today
Hi,
I have been using the same code to hash some information, but since a couple days Homeyscript gives an error on the crypto library.
This piece: const crypto = (this.constructor.constructor('return process.mainModule.require')())('crypto');
does not work anymore:
TypeError: Cannot read properties of undefined (reading 'require')
I have rebooted the Homey Pro and rebooted the Homeyscript app without success. Also checked if I have the latest Homey Script version, which i do.
I hope someone (I’m looking at you @robertklep ) has a solution for this
Looks like process.mainModule
was dropped from Node.js (either because it’s been deprecated for a while now, or Athom has removed it intentionally).
If you need to calculate an SHA1 hash, the only solution I can think of right now is to add a pure-JS implementation of the SHA1 algorithm to your script:
const hs = Array.from(Array(16), (_, i) => i.toString(16));
const hsr = hs.slice().reverse();
const h2s = hs.join("").match(/../g), h2sr = hsr.join("").match(/../g);
const h2mix = hs.map((h, i) => `${hsr[i]}${h}`);
const hseq = h2s.concat(h2sr, h2mix).map(hex => parseInt(hex, 16));
const H = new Uint32Array(Uint8Array.from(hseq.slice(0, 20)).buffer);
const K = Uint32Array.from(
[2, 3, 5, 10], v => Math.floor(Math.sqrt(v) * (2 ** 30)));
const F = [
(b, c, d) => ((b & c) | ((~b >>> 0) & d)) >>> 0,
(b, c, d) => b ^ c ^ d,
(b, c, d) => (b & c) | (b & d) | (c & d),
(b, c, d) => b ^ c ^ d,
];
function rotl(v, n) {
return ((v << n) | (v >>> (32 - n))) >>> 0;
}
function sha1(buffer) {
const u8a = ArrayBuffer.isView(buffer) ?
new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength) :
new Uint8Array(buffer);
const total = Math.ceil((u8a.length + 9) / 64) * 64;
const chunks = new Uint8Array(total);
chunks.set(u8a);
chunks.fill(0, u8a.length);
chunks[u8a.length] = 0x80;
const lenbuf = new DataView(chunks.buffer, total - 8);
const low = u8a.length % (1 << 29);
const high = (u8a.length - low) / (1 << 29);
lenbuf.setUint32(0, high, false);
lenbuf.setUint32(4, low << 3, false);
const hash = H.slice();
const w = new Uint32Array(80);
for (let offs = 0; offs < total; offs += 64) {
const chunk = new DataView(chunks.buffer, offs, 64);
for (let i = 0; i < 16; i++) w[i] = chunk.getUint32(i * 4, false);
for (let i = 16; i < 80; i++) {
w[i] = rotl(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1);
}
let [a, b, c, d, e] = hash;
for (let s = 0; s < 4; s++) {
for (let i = s * 20, end = i + 20; i < end; i++) {
const ne = rotl(a, 5) + F[s](b, c, d) + e + K[s] + w[i];
[a, b, c, d, e] = [ne >>> 0, a, rotl(b, 30), c, d];
}
}
hash[0] += a; hash[1] += b; hash[2] += c; hash[3] += d; hash[4] += e;
}
const digest = new DataView(new ArrayBuffer(20));
hash.forEach((v, i) => digest.setUint32(i * 4, v, false));
return Buffer.from(digest.buffer).toString('hex');
}
(source)
Usage example:
const hash = sha1('some input string');
console.log( hash );
Thank you very much!
I gave the code a try and found that it was not working as expected. The hash returned was for a blank value so whatever you passed would give the same results. With a bit of playing I found the above secion of code needed to be changed for it to work. Once I made the adjustment I tested the rest of the code against other sha1 hash generators and its working perfectly now:
const u8a = new Uint8Array(buffer.length);
for(i=0;i<buffer.length;i+=1) {
u8a[i]=buffer.codePointAt(i);
}
Ah yes, the code assumes the input data is passed as a buffer, which won’t be the case with Homey.
In that case, a faster fix would be:
const u8a = ArrayBuffer.isView(buffer) ?
new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength) :
new Uint8Array(Buffer.from(buffer));
Thankyou very much - this really helps