Created
January 26, 2022 20:12
-
-
Save dashameter/a929f7179c9f6a49f8c1ef475d498002 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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