|
@@ -1,79 +1,74 @@
|
|
|
-const NodeRSA = require('node-rsa')
|
|
|
const { serializeBytes } = require('../tl')
|
|
|
const { readBigIntFromBuffer, readBufferFromBigInt, getByteArray, sha1, generateRandomBytes, modExp } = require('../Helpers')
|
|
|
const _serverKeys = {}
|
|
|
const BigInt = require('big-integer')
|
|
|
|
|
|
|
|
|
+/**
|
|
|
+ * Given a RSA key, computes its fingerprint like Telegram does.
|
|
|
+ * @param key the RSA key.
|
|
|
+ * @returns {bigInt.BigInteger|*} its 8-bytes-long fingerprint
|
|
|
+ * @private
|
|
|
+ */
|
|
|
function _computeFingerprint(key) {
|
|
|
- const buf = readBigIntFromBuffer(key.keyPair.n.toBuffer(), false)
|
|
|
- const nArray = getByteArray(buf)
|
|
|
|
|
|
- const n = serializeBytes(nArray)
|
|
|
- const e = serializeBytes(getByteArray(key.keyPair.e))
|
|
|
+ const n = serializeBytes(getByteArray(key.n))
|
|
|
+ const e = serializeBytes(getByteArray(key.e))
|
|
|
// Telegram uses the last 8 bytes as the fingerprint
|
|
|
- const sh = sha1(Buffer.concat([ n, e ]))
|
|
|
+ const sh = sha1(Buffer.concat([n, e]))
|
|
|
return readBigIntFromBuffer(sh.slice(-8), true, true)
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * Adds a new public key to be used when encrypting new data is needed
|
|
|
+ * @param pub {{n:BigInt,e:BigInt}}
|
|
|
+ */
|
|
|
function addKey(pub) {
|
|
|
- const key = new NodeRSA(pub)
|
|
|
- _serverKeys[_computeFingerprint(key)] = key
|
|
|
+ _serverKeys[_computeFingerprint(pub)] = pub
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * Encrypts the given data known the fingerprint to be used
|
|
|
+ * in the way Telegram requires us to do so (sha1(data) + data + padding)
|
|
|
+
|
|
|
+ * @param fingerprint the fingerprint of the RSA key.
|
|
|
+ * @param data the data to be encrypted.
|
|
|
+ * @returns {Buffer|*|undefined} the cipher text, or None if no key matching this fingerprint is found.
|
|
|
+ */
|
|
|
function encrypt(fingerprint, data) {
|
|
|
const key = _serverKeys[fingerprint]
|
|
|
if (!key) {
|
|
|
return undefined
|
|
|
}
|
|
|
- const buf = readBigIntFromBuffer(key.keyPair.n.toBuffer(), false)
|
|
|
+
|
|
|
+ // len(sha1.digest) is always 20, so we're left with 255 - 20 - x padding
|
|
|
const rand = generateRandomBytes(235 - data.length)
|
|
|
const toEncrypt = Buffer.concat([sha1(data), data, rand])
|
|
|
+
|
|
|
+ // rsa module rsa.encrypt adds 11 bits for padding which we don't want
|
|
|
+ // rsa module uses rsa.transform.bytes2int(to_encrypt), easier way:
|
|
|
const payload = readBigIntFromBuffer(toEncrypt, false)
|
|
|
- const encrypted = modExp(payload, BigInt(key.keyPair.e), buf)
|
|
|
- const block = readBufferFromBigInt(encrypted, 256, false)
|
|
|
- return block
|
|
|
+ const encrypted = modExp(payload, BigInt(key.e), key.n)
|
|
|
+ // rsa module uses transform.int2bytes(encrypted, keylength), easier:
|
|
|
+ return readBufferFromBigInt(encrypted, 256, false)
|
|
|
}
|
|
|
|
|
|
-const publicKeys = [
|
|
|
- `-----BEGIN RSA PUBLIC KEY-----
|
|
|
-MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6
|
|
|
-lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS
|
|
|
-an9tqw3bfUV/nqgbhGX81v/+7RFAEd+RwFnK7a+XYl9sluzHRyVVaTTveB2GazTw
|
|
|
-Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+
|
|
|
-8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n
|
|
|
-Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
|
|
|
------END RSA PUBLIC KEY-----`,
|
|
|
-
|
|
|
- `-----BEGIN RSA PUBLIC KEY-----
|
|
|
-MIIBCgKCAQEAxq7aeLAqJR20tkQQMfRn+ocfrtMlJsQ2Uksfs7Xcoo77jAid0bRt
|
|
|
-ksiVmT2HEIJUlRxfABoPBV8wY9zRTUMaMA654pUX41mhyVN+XoerGxFvrs9dF1Ru
|
|
|
-vCHbI02dM2ppPvyytvvMoefRoL5BTcpAihFgm5xCaakgsJ/tH5oVl74CdhQw8J5L
|
|
|
-xI/K++KJBUyZ26Uba1632cOiq05JBUW0Z2vWIOk4BLysk7+U9z+SxynKiZR3/xdi
|
|
|
-XvFKk01R3BHV+GUKM2RYazpS/P8v7eyKhAbKxOdRcFpHLlVwfjyM1VlDQrEZxsMp
|
|
|
-NTLYXb6Sce1Uov0YtNx5wEowlREH1WOTlwIDAQAB
|
|
|
------END RSA PUBLIC KEY-----`,
|
|
|
-
|
|
|
- `-----BEGIN RSA PUBLIC KEY-----
|
|
|
-MIIBCgKCAQEAsQZnSWVZNfClk29RcDTJQ76n8zZaiTGuUsi8sUhW8AS4PSbPKDm+
|
|
|
-DyJgdHDWdIF3HBzl7DHeFrILuqTs0vfS7Pa2NW8nUBwiaYQmPtwEa4n7bTmBVGsB
|
|
|
-1700/tz8wQWOLUlL2nMv+BPlDhxq4kmJCyJfgrIrHlX8sGPcPA4Y6Rwo0MSqYn3s
|
|
|
-g1Pu5gOKlaT9HKmE6wn5Sut6IiBjWozrRQ6n5h2RXNtO7O2qCDqjgB2vBxhV7B+z
|
|
|
-hRbLbCmW0tYMDsvPpX5M8fsO05svN+lKtCAuz1leFns8piZpptpSCFn7bWxiA9/f
|
|
|
-x5x17D7pfah3Sy2pA+NDXyzSlGcKdaUmwQIDAQAB
|
|
|
------END RSA PUBLIC KEY-----`,
|
|
|
-
|
|
|
- `-----BEGIN RSA PUBLIC KEY-----
|
|
|
-MIIBCgKCAQEAwqjFW0pi4reKGbkc9pK83Eunwj/k0G8ZTioMMPbZmW99GivMibwa
|
|
|
-xDM9RDWabEMyUtGoQC2ZcDeLWRK3W8jMP6dnEKAlvLkDLfC4fXYHzFO5KHEqF06i
|
|
|
-qAqBdmI1iBGdQv/OQCBcbXIWCGDY2AsiqLhlGQfPOI7/vvKc188rTriocgUtoTUc
|
|
|
-/n/sIUzkgwTqRyvWYynWARWzQg0I9olLBBC2q5RQJJlnYXZwyTL3y9tdb7zOHkks
|
|
|
-WV9IMQmZmyZh/N7sMbGWQpt4NMchGpPGeJ2e5gHBjDnlIf2p1yZOYeUYrdbwcS0t
|
|
|
-UiggS4UeE8TzIuXFQxw7fzEIlmhIaq3FnwIDAQAB
|
|
|
------END RSA PUBLIC KEY-----`,
|
|
|
-]
|
|
|
+const publicKeys = [{
|
|
|
+ 'n': BigInt('24403446649145068056824081744112065346446136066297307473868293895086332508101251964919587745984311372853053253457835208829824428441874946556659953519213382748319518214765985662663680818277989736779506318868003755216402538945900388706898101286548187286716959100102939636333452457308619454821845196109544157601096359148241435922125602449263164512290854366930013825808102403072317738266383237191313714482187326643144603633877219028262697593882410403273959074350849923041765639673335775605842311578109726403165298875058941765362622936097839775380070572921007586266115476975819175319995527916042178582540628652481530373407'),
|
|
|
+ 'e': 65537
|
|
|
+}, {
|
|
|
+ 'n': BigInt('25081407810410225030931722734886059247598515157516470397242545867550116598436968553551465554653745201634977779380884774534457386795922003815072071558370597290368737862981871277312823942822144802509055492512145589734772907225259038113414940384446493111736999668652848440655603157665903721517224934142301456312994547591626081517162758808439979745328030376796953660042629868902013177751703385501412640560275067171555763725421377065095231095517201241069856888933358280729674273422117201596511978645878544308102076746465468955910659145532699238576978901011112475698963666091510778777356966351191806495199073754705289253783'),
|
|
|
+ 'e': 65537
|
|
|
+}, {
|
|
|
+ 'n': BigInt('22347337644621997830323797217583448833849627595286505527328214795712874535417149457567295215523199212899872122674023936713124024124676488204889357563104452250187725437815819680799441376434162907889288526863223004380906766451781702435861040049293189979755757428366240570457372226323943522935844086838355728767565415115131238950994049041950699006558441163206523696546297006014416576123345545601004508537089192869558480948139679182328810531942418921113328804749485349441503927570568778905918696883174575510385552845625481490900659718413892216221539684717773483326240872061786759868040623935592404144262688161923519030977'),
|
|
|
+ 'e': 65537
|
|
|
+}, {
|
|
|
+ 'n': BigInt('24573455207957565047870011785254215390918912369814947541785386299516827003508659346069416840622922416779652050319196701077275060353178142796963682024347858398319926119639265555410256455471016400261630917813337515247954638555325280392998950756512879748873422896798579889820248358636937659872379948616822902110696986481638776226860777480684653756042166610633513404129518040549077551227082262066602286208338952016035637334787564972991208252928951876463555456715923743181359826124083963758009484867346318483872552977652588089928761806897223231500970500186019991032176060579816348322451864584743414550721639495547636008351'),
|
|
|
+ 'e': 65537
|
|
|
+}]
|
|
|
for (const pub of publicKeys) {
|
|
|
addKey(pub)
|
|
|
}
|
|
|
|
|
|
module.exports = { encrypt, addKey }
|
|
|
+
|