Skip to content

Instantly share code, notes, and snippets.

@dashameter
Created January 26, 2022 20:12
Show Gist options
  • Save dashameter/a929f7179c9f6a49f8c1ef475d498002 to your computer and use it in GitHub Desktop.
Save dashameter/a929f7179c9f6a49f8c1ef475d498002 to your computer and use it in GitHub Desktop.
const Dash = require("dash");
const CryptoJS = require("crypto-js");
// const secp256k1 = require("secp256k1-native");
const secp256k1 = require("secp256k1/elliptic");
const dashcore = require("@dashevo/dashcore-lib");
// sender, receiver must be friends (existing contactRequest documents on dpp)
// changing mnemonic requires adjusting or removing skipSynchronizationBeforeHeight
// const senderMnemonic = 'alert escape pear enhance mansion gossip seminar mansion enable salt bounce tumble'; // A-DashpayJS
// const receiverUsername = 'B-DashpayJS';
// const senderMnemonic = 'catalog world quit margin supreme pony vacuum park inch soul daughter manage'; // B-DashpayJS
// const receiverUsername = 'A-DashpayJS';
const senderMnemonic =
"soap minor liberty divert scrub comic mail stable crouch naive mouse fringe"; // high
const receiverUsername = "lowhangingfruit";
const decryptCBCAES256 = (encrypted, secret, enc) => {
const encodings = {
hex: CryptoJS.enc.Hex,
utf8: CryptoJS.enc.Utf8,
base64: CryptoJS.enc.Base64,
};
const key = CryptoJS.enc.Hex.parse(secret.toString("hex"));
const iv = CryptoJS.enc.Hex.parse(encrypted.slice(0, 16).toString("hex"));
const ciphertext = CryptoJS.enc.Hex.parse(
encrypted.slice(16, encrypted.length).toString("hex")
);
const encryptedCP = CryptoJS.lib.CipherParams.create({
ciphertext,
formatter: CryptoJS.format.OpenSSL, // Optional, but required for encryptedCP.toString()
});
const decryptedWA = CryptoJS.AES.decrypt(encryptedCP, key, { iv });
const decrypted = decryptedWA.toString(encodings[enc]);
return decrypted;
};
const clientOpts = {
network: "testnet",
// dapiAddresses: ["34.220.41.134", "18.236.216.191", "54.191.227.118"],
wallet: {
mnemonic: senderMnemonic,
unsafeOptions: {
skipSynchronizationBeforeHeight: 485512,
},
},
// apps: {
// dashpay: {
// contractId: "2DAncD4YTjfhSQZYrsQ659xbM7M5dNEkyfBEAg9SsS3W",
// },
// },
};
const client = new Dash.Client(clientOpts);
const main = async () => {
client.account = await client.getWalletAccount();
const senderIdentityId = client.account.identities.getIdentityIds()[0];
const receiverDPNS = await client.platform.names.resolve(
`${receiverUsername}.dash`
);
const receiverIdentity = await client.platform.identities.get(
receiverDPNS.ownerId.toString()
);
console.log("receiverIdentity.toJSON() :>> ", receiverIdentity.toJSON());
const contactRequests = await client.platform.documents.get(
"dashpay.contactRequest",
{
limit: 1,
where: [
["$ownerId", "==", receiverIdentity.getId()],
["toUserId", "==", senderIdentityId],
],
}
);
console.log("contactRequests :>> ", contactRequests[0].toJSON());
// ECDH Shared Key / Diffie-Hellman Key Exchange
const receiverPublicKey = receiverIdentity.toJSON().publicKeys[0].data;
const senderPrivateKey = client.account.identities
.getIdentityHDKeyByIndex(0, 0)
.privateKey.toString();
console.log("senderPrivateKey :>> ", senderPrivateKey);
const point = Buffer.from(receiverPublicKey, "base64");
const scalar = Buffer.from(senderPrivateKey, "hex");
// compressed public key from X and Y
function hashfn(x, y) {
const pubKey = new Uint8Array(33);
pubKey[0] = (y[31] & 1) === 0 ? 0x02 : 0x03;
pubKey.set(x, 1);
return pubKey;
}
// get X point of ecdh
const ecdhPointX = secp256k1.ecdh(
point,
scalar,
{ hashfn },
Buffer.alloc(33)
);
console.log("sharedSecret", ecdhPointX.toString("hex"));
const sharedSecret = ecdhPointX;
// CBC-AES-256 decryption
const { encryptedAccountLabel, encryptedPublicKey } = contactRequests[0].data;
console.log("encryptedAccountLabel :>> ", encryptedAccountLabel.length);
// Decrypt accountLabel
const decryptedAccountLabel = decryptCBCAES256(
encryptedAccountLabel,
sharedSecret,
"utf8"
);
console.log("decryptedAccountLabel :>> ", decryptedAccountLabel);
// Decrypt publicKey
const decryptedPublicKey = decryptCBCAES256(
encryptedPublicKey,
sharedSecret,
"hex"
);
console.log("decryptedPublicKey :>> ", decryptedPublicKey);
// Derive receiving address
const xpubkeyBuffers = Buffer.from(decryptedPublicKey, "hex");
const parentFingerPrint = xpubkeyBuffers.slice(0, 4);
const chainCode = xpubkeyBuffers.slice(4, 36);
const publicKey = xpubkeyBuffers.slice(36, 69);
const depth = Buffer.alloc(1);
const childIndex = Buffer.alloc(4);
const xpubkey = dashcore.HDPublicKey.fromObject({
parentFingerPrint,
chainCode,
publicKey,
network: "testnet",
depth,
childIndex,
});
const receivingAddress = dashcore
.Address(xpubkey.publicKey, "testnet")
.toString();
console.log("receivingAddress :>> ", receivingAddress);
const transaction = client.account.createTransaction({
recipient: receivingAddress,
satoshis: 10000000, // 0.1 Dash
});
const tx = await client.account.broadcastTransaction(transaction);
console.log("tx :>> ", tx);
};
main()
.then(() => console.log("Success!"))
.catch((e) => console.error("Something went wrong:\n", e))
.finally(() => client.disconnect());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment