how to decrypt sha-256 encrypted text cloudflare workers - node.js

I want to decrypt encrypted string, but when try to decrypt it using Textdecoder it return error. . Here is the error TypeError: Failed to execute 'decode' on 'TextDecoder': parameter 1 is not of type 'Array'.
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
const message = "81706cd5bd5049fc200560d3c9efada6418358e09bc135d3de4fa91817fb4768";
const msgUint8 = new TextDecoder().decode(message)
const hashBuffer = await crypto.subtle.digest('SHA-256', msgUint8)
const hashArray = Array.from(new Uint8Array(hashBuffer))
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('')
return new Response(hashHex, {status: 200})
}

Related

tronWeb getAccount returns null

(async function () {
const TronWeb = require('tronweb');
const HttpProvider = TronWeb.providers.HttpProvider;
const fullNode = new HttpProvider('https://api.trongrid.io');
const solidityNode = new HttpProvider('https://api.trongrid.io');
const eventServer = 'https://api.trongrid.io/';
const privateKey = "04EE63599802B5D31A29C95CC7DF04F427E8F0A124BED9333F3A80404ACFC3127659C540D0162DEDB81AC5F74B2DEB4962656EFE112B252E54AC3BA1207CD1FB1004EE63599802B5D31A29C95CC7DF04F427E8F0A124BED9333F3A80404ACFC3127659C540D0162DEDB81AC5F74B2DEB4962656EFE112B252E54AC3BA1207CD1FB10";
const apiKey ='92959baa-2df2-4292-8309-d87ef88a56d6';
const tronWeb = new TronWeb(fullNode, solidityNode, eventServer, privateKey)
tronWeb.setHeader({"TRON-PRO-API-KEY": '92959baa-xxx-4292-xxx-d87xxa56d6'});
const newAccount = await tronWeb.createAccount();
//return {
privateKey: 'xxxxxxxxx',
publicKey: 'xxxxxxxxxx',
address: {
base58: 'TURYhSKCw3m84MaKmYhoYqd72ULHRn5zJy',
hex: '41CA6D8549A64DA49324248140789B5A4F52EB022B'
}
}
const account = await tronWeb.trx.getAccount('TURYhSKCw3m84MaKmYhoYqd72ULHRn5zJy');
console.log(account) // returns null object {}
})()
if i try tronWeb.trx.getAccount function it returns null, i asked CHATGPT it said possible this wallet hasnt any transaction that why it returns null,
but i deposited 5 usdt to "TX5pWLD2LbaUaF56L4w7Pqwtg2Wp7eKDZ3" this wallet created by tronWeb.createAccount() when i try request i am getting same action.
uys what is the problem any body can solve this?
i am trying create some wallets TRC20 USDT deposit,transactions etc..
(i used tronweb#4.4 and tronweb#3.2 given same null object result)

How can i get a client side cookie with next.js 13 before rendering from middleware

I am trying to get a cookie from the middleware of Nextjs 13 and I can't find up to date information on this.
My question: is there a way to see the cookie before rendering the html.
window is fined or something?
page.tsx
async function getData() {
const nextCookies = cookies(); // Get cookies object
try {
let cityToken = nextCookies.get('regionCode'); // Find cookie city
return cityToken;
} catch (e) {
console.log(e);
}
}
export default async function Page() {
const nextCookies = cookies(); // Get cookies object
const token = nextCookies.get('new'); // Find cookie for is new user
// const cityToken = await getData();
const cityToken = cookies().get('regionCode')?.value;
console.log(cityToken);
}
middleware.tsx
const myFunction = async () => {
// https://geolocation.onetrust.com/cookieconsentpub/v1/geo/location
// run asynchronous tasks here - ip location
const response = await fetch('https://www.cloudflare.com/cdn-cgi/trace');
const text = await response.text();
const arr = text.split('\n');
const ip = arr.filter((v) => v.includes('ip='))[0].split('=')[1];
// https://stackoverflow.com/questions/65752416/how-can-i-most-easily-parse-this-http-response-into-json-to-then-access-response
// https://stackoverflow.com/questions/64591296/access-to-fetch-at-https-www-cloudflare-com-cdn-cgi-trace-from-origin-http
const ipCity = await fetch(`https://ipapi.co/${ip}/json/`);
const textJson = await ipCity.json();
};
const data = await myFunction();
res.cookies.set('regionCode', 'textJson.region');

In cloudflare worker how to get data from url

How to get data params from url and decrypt using the function below in cloudflare worker.https://SOMEID.srv10.workers.dev/hash/ So i want to get hash and decrypt that using that function.
async function decryptData(encryptedData, password) {
try {
// split the IV off from the end (delimited using ::)
encryptedComponents= encryptedData.split("::")
const data = hexStringToUint8Array(encryptedComponents[0])
const iv = hexStringToUint8Array(encryptedComponents[1])
const passwordKey = await getPasswordKey(password, ['decrypt'])
const decryptedContent = await crypto.subtle.decrypt(
{
name: 'AES-CBC',
iv: iv,
},
passwordKey,
data,
)
return arraybufferToString(decryptedContent)
} catch (e) {
throw e
}
}
Assuming your hash is a query parameter you can simply read it like so:
// convert the worker request url into a URL object
const url = new URL(request.url);
// read the encrypted data from the query param
const encryptedData = url.searchParams.get('hash');
// call your function
await decryptData(encryptedData, '<your-password-here>');

NodeJS Crypto Fails to Verify Signature Created by Web Crypto API

I'm having troubles verifying signatures created by the Web Crypto API.
Here is the code I'm using to generate RSA keys in the browser:
let keys;
const generateKeys = async () => {
const options = {
name: 'RSASSA-PKCS1-v1_5',
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: { name: 'SHA-256' },
};
keys = await window.crypto.subtle.generateKey(
options,
false, // non-exportable (public key still exportable)
['sign', 'verify'],
);
};
And to export the public key:
const exportPublicKey = async () => {
const publicKey = await window.crypto.subtle.exportKey('spki', keys.publicKey);
let body = window.btoa(String.fromCharCode(...new Uint8Array(publicKey)));
body = body.match(/.{1,64}/g).join('\n');
return `-----BEGIN PUBLIC KEY-----\n${body}\n-----END PUBLIC KEY-----`;
// Output:
//
// -----BEGIN PUBLIC KEY-----
// MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAx7J3SUG4sq/HSGIaGZWY
// 8b26cfEpVFYHoDUDUORIJzA/fLE9aj+uOKpGUTSfW69rMm7DAOLDz05KaEJJSI5+
// YbDPr2S82A2ByHHQt+Vu168sGz4noXTTSX2HIdVutaR/IJ0a5pNOa1vRR4MUW/ZO
// YaRir3yC5YXgcFLwwQaifNZ3lZ7WndbYEjTGOcieQQ81IUP2221PZCJI52S95nYm
// VfslsLiPhOFH7XhGSqelGYDi0cKyl0p6dKvYxFswfKKLTuWnu2BEFLjVq4S5Y9Ob
// SGm0KL/8g7pAqjac2sMzzhHtxZ+7k8tynzAf4slJJhHMm5U4DcSelTe5zOkprCJg
// muyv0H1Acb3tfXsBwfURjiE0cvSMhfum5I5epF+f139tsr1zNF24F2WgvEZZbXcG
// g1LveGCJ/0BY0pzE71DU2SYiUhl+HGDv2u32vJO80jCDf2lu7izEt544a+XE+2X0
// zVpwjNQGa2Nd4ApGosa1fbcS5MsEdbyrjMf80SAmOeb9g3y5Zt2MY7M0Njxbvmmd
// mF20PkklpH0L01lhg2AGma4o4ojolYHzDoM5a531xTw1fZIdgbSTowz0SlAHAKD3
// c2KCCsKlBbFcqy4q7yNX63SqmI3sNA3kTH9CQJdBloRvV103Le9C0iY8CAWQmow5
// N/sDJUabgOMqe9yopSjb7LUCAwEAAQ==
// -----END PUBLIC KEY-----
};
To sign a message:
const generateHash = async (message) => {
const encoder = new TextEncoder();
const buffer = encoder.encode(message);
const digest = await window.crypto.subtle.digest('SHA-256', buffer);
return digest;
};
const signMessage = async (message) => {
const { privateKey } = keys;
const digest = await generateHash(message);
const signature = await window.crypto.subtle.sign('RSASSA-PKCS1-v1_5', privateKey, digest);
return signature;
};
To verify the message in browser:
const verifyMessage = async (signature, message) => {
const { publicKey } = keys;
const digest = await generateHash(message);
const result = await window.crypto.subtle.verify('RSASSA-PKCS1-v1_5', publicKey, signature, digest);
return result;
};
When the keys are created, the public key is exported and sent to the server. Later:
const message = 'test';
const signature = await signMessage(message);
await verifyMessage(signature, message); // true
sendToServer(message, bufferToHex(signature));
Since the signature is an ArrayBuffer, I convert it to hex with the following code:
const bufferToHex = input => [...new Uint8Array(input)]
.map(v => v.toString(16).padStart(2, '0')).join('');
On the server (NodeJS 8.11.0):
const publicKey = getPublicKey(userId);
const verifier = crypto.createVerify('RSA-SHA256');
verifier.update(message, 'utf-8');
const sigBuf = Buffer.from(signature, 'hex');
verifier.verify(publicKey, sigBuf); // false
I've been chasing down this issue for days and just cannot seem to figure it out. I've tried both RSA-SHA256 and sha256WithRSAEncryption for verification to no avail. Furthermore, no errors are being thrown. Any help would be enormously appreciated!
So I don't fully understand why this is the case, but to solve the issue I needed to convert the SHA hash from an ArrayBuffer into a hex string, then read back into an array buffer using TextEncoder.
const generateHash = async (message) => {
const encoder = new TextEncoder();
const buffer = encoder.encode(message);
const digest = await window.crypto.subtle.digest('SHA-256', buffer);
// Convert to hex string
return [...new Uint8Array(digest)]
.map(v => v.toString(16).padStart(2, '0')).join('');;
};
Then when signing:
const signMessage = async (message) => {
const encoder = new TextEncoder();
const { privateKey } = keys;
const digest = await generateHash(message);
const signature = await window.crypto.subtle.sign('RSASSA-PKCS1-v1_5', privateKey, encoder.encode(digest));
return signature;
};
The signature no longer verifies on the client but it verifies in node. 🤷‍♂️
The issue is that you are signing the hash of hash of your input when you should actually be signing hash of your input. SubtleCrypto internally hashes the input. There is no need for you to provide hashed input. Since you provided hashed input as an argument, SubtleCrypto hashed it again and then signed it which led to mismatch of signatures.
It may be useful to note that both crypto and crypto.subtle hash the message before signing, so hashing separately is not necessary.
Assuming you were able to create and load your keys properly, your code should look like this.
Browser
const message = 'hello'
const encoder = new TextEncoder()
const algorithmParameters = { name: 'RSASSA-PKCS1-v1_5' }
const signatureBytes = await window.crypto.subtle.sign(
algorithmParameters,
privateKey,
encoder.encode(message)
)
const base64Signature = window.btoa(
String.fromCharCode.apply(null, new Uint8Array(signatureBytes))
)
console.log(base64Signature)
// TiJZTTihhUYAIlOm2PpnvJa/+15WOX2U0iKJ2LXsLecvohhRIWnwFfdHy4ci10mcv/UQgf2+bFf9lfFZUlPPdzckBNfXIqAjafM8XquJiw/t1v+pEGtJpaGASlzuWuL37gp3k8ux3l6zBKKbBVPPASkHVhz37uY1AXeMblfRbFE=
Node
This implementation is using crypto, but you could use the crypto.subtle to be more similar to the browser javascript syntax
const crypto = require('crypto')
const message = 'hello'
const base64Signature = 'TiJZTTihhUYAIlOm2PpnvJa/+15WOX2U0iKJ2LXsLecvohhRIWnwFfdHy4ci10mcv/UQgf2+bFf9lfFZUlPPdzckBNfXIqAjafM8XquJiw/t1v+pEGtJpaGASlzuWuL37gp3k8ux3l6zBKKbBVPPASkHVhz37uY1AXeMblfRbFE='
const hashingAlgorithm = 'rsa-sha256'
const doesVerify = crypto.verify(
hashingAlgorithm,
Buffer.from(message),
{ key: publicKey },
Buffer.from(base64Signature, 'base64')
);
console.log(doesVerify)
// true
Not a direct answer but it might just be easier to use this: https://www.npmjs.com/package/#peculiar/webcrypto so your code on client and server is consistent while addressing this problem at the same time.

Global scope variable initialization in google cloud function

I want to store a secret key using Google Cloud KMS and use it in Google Cloud Function. First I will encrypt my key and store it in environment variable
If I decrypt my secret key like link, it returns Promise.
Is my variable guaranteed to be finished initializing when my function is deployed and called?
I'm the author of that code snippet and the corresponding blog post. For the post history, here's the full snippet the OP is referring to:
const cryptoKeyID = process.env.KMS_CRYPTO_KEY_ID;
const kms = require('#google-cloud/kms');
const client = new kms.v1.KeyManagementServiceClient();
let username;
client.decrypt({
name: cryptoKeyID,
ciphertext: process.env.DB_USER,
}).then(res => {
username = res[0].plaintext.toString().trim();
}).catch(err => {
console.error(err);
});
let password;
client.decrypt({
name: cryptoKeyID,
ciphertext: process.env.DB_PASS,
}).then(res => {
password = res[0].plaintext.toString().trim();
}).catch(err => {
console.error(err);
});
exports.F = (req, res) => {
res.send(`${username}:${password}`)
}
Because Node is an asynchronous language, there is no guarantee that the variables username and password are fully initialized before function invocation as-written. In that snippet, I optimized for "decrypt at function boot so each function invocation runs in constant time". In your example, you want to optimize for "the function is fully initialized before invocation" which requires some re-organization of the code.
One possible solution is to move the lookup into a Node function that is invoked when the GCF function is called. For example:
const cryptoKeyID = process.env.KMS_CRYPTO_KEY_ID;
const kms = require('#google-cloud/kms');
const client = new kms.v1.KeyManagementServiceClient();
let cache = {};
const decrypt = async (ciphertext) => {
if (!cache[ciphertext]) {
const [result] = await client.decrypt({
name: cryptoKeyID,
ciphertext: ciphertext,
});
cache[ciphertext] = result.plaintext;
}
return cache[ciphertext];
}
exports.F = async (req, res) => {
const username = await decrypt(process.env.DB_USER);
const password = await decrypt(process.env.DB_PASS);
res.send(`${username}:${password}`)
}
Note that I added a caching layer here, since you probably don't want to decrypt the encrypted blob on each invocation of the function.

Resources