NodeJS RSA prehashed sign - node.js

I'm running NodeJS 8.12.0 and have to set a signature over a hash, without re-hashing it, performing a raw signature. Or, in other words, encrypt the hashed value with the private key.
const crypto = require('crypto');
// 4096 bits key.
let pk = "<BASE64 DER>";
let pub = "<BASE64 DER>";
// Transform them to PEM.
pk = `-----BEGIN PRIVATE KEY-----\n${pk.replace('\n', '')}\n-----END PRIVATE KEY-----\n`;
pub = `-----BEGIN PUBLIC KEY-----\n${pub.replace('\n', '')}\n-----END PUBLIC KEY-----\n`;
// Load the data to sign and set the signature.
const fingerprint = Buffer.from('2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824','hex');
const signature = crypto.privateEncrypt({
key: pk,
padding: crypto.constants.RSA_PKCS1_PADDING
},
fingerprint
);
// Unfortunately, the server is not able to verify the signature...
console.log(signature.toString('hex'));
So I took a look at raw encryption of the message hash with my private key and ended up with some sort of EMSA encoding and followed these steps:
Apply the hash function to the message
Encode the algorithm ID for the hash function and the hash into ASN.1 value of DigestInfo (Appendix A.2.4)
Generate an octet string PS consisting of emLen - tLen - 3 octets of 0xff
Concatenate PS, the DER encoded value T, and other padding to form the encoded message EM as EM = 0x00 || 0x01 || PS || 0x00 || T
So, working that out
// 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
H = 2c f2 4d ba 5f b0 a3 0e 26 e8 3b 2a c5 b9 e2 9e 1b 16 1e 5c 1f a7 42 5e 73 04 33 62 93 8b 98 24
emLen = 512
T = 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 2c f2 4d ba 5f b0 a3 0e 26 e8 3b 2a c5 b9 e2 9e 1b 16 1e 5c 1f a7 42 5e 73 04 33 62 93 8b 98 24
PS = 04 06 02 00 33 ff ff ff
// 00010406020033ffffff003031300d0609608648016503040201050004202cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
EM = 00 01 04 06 02 00 33 ff ff ff 00 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 2c f2 4d ba 5f b0 a3 0e 26 e8 3b 2a c5 b9 e2 9e 1b 16 1e 5c 1f a7 42 5e 73 04 33 62 93 8b 98 24
But when I put that into the privateEncrypt, I do not get the correct output either. Can anyone help me here?

You are trying to do the PKCS1-padding (RSASSA-PKCS1-V1_5) manually. But this isn't necessary. It's enough to concatenate the Hash-ID (here for SHA-256) and your data (fingerprint), the rest is done by the implicitly selected padding (crypto.constants.RSA_PKCS1_PADDING), i.e.
// Signing
var fingerprint = Buffer.from('2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824','hex');
var id = Buffer.from([0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20]);
var allData = Buffer.concat([id, fingerprint]);
var signature = crypto.privateEncrypt(privateKey, allData); // crypto.constants.RSA_PKCS1_PADDING by default
// Verifying with createVerify
var verify = crypto.createVerify('RSA-SHA256');
verify.update('<the signed data>');
var verified = verify.verify(publicKey, signature); // provides true
// Verifying with publicDecrypt
var decryptedFingerprint = crypto.publicDecrypt(publicKey, Buffer.from(signature)).slice(-32); // provides fingerprint
Note: If you want to do the padding manually, you have to set the byte sequence 0x00 || 0x01 || PS || 0x00 before the allData-buffer. PS consists of as many 0xff-bytes as necessary to reach the key length (in bytes). In addition, the flag
crypto.constants.RSA_NO_PADDING must be set explicitly in the privateEncrypt-call. However, this isn't necessary, since the result is the same. The details are described in RFC 8017, Section 8.2.1

Related

How to change specific byte in packet using scapy?

I want to modify icmp.unused value in scapy. But no matter what value I set for it, the value of icmp.unused is still 0. I know which byte in my packet is responsible for its value. So I want to modify the byte directly. hexstr and hexdump don't work. The end of the packet is messed up. How to do this?
hex_packet = scapy.hexstr(packet)
print(type(hex_packet))
list_packet = list(hex_packet)
list_packet[38] = '\x05'
list_packet[39] = '\x14'
hex_packet = ''.join(list_packet)
packet_hex = scapy.Ether(scapy.import_hexcap())
08 00 27 78 FE 4B 52 54 00 12 35 00 080 45 00 00 38 00 01 00 00 40 01 31 6D C0 A8 64 01 C0 A8 64 05 03 04 41 5E 00 00 05 14 45 00 00 1C 00 01 00 00 40 11 31 74 C0 A8 64 05 C0 A8 64 06 FC F1 00 35 00 08 B9 5A ..'x.KRT..5...E..8....#.1m..d...d...A^....E.......#.1t..d...d....5...Z

How to build PlayReady Object from pssh

My PSSH-Box for PlayReady is below in base64 and hex format.
"playready": {
"pssh-base64": "AAAD4nBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAA8LCAwAAAQABALgDPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgB2ADgAMgByAHMARwBsADUATgAwAE8AdQBLADgAcgBPAEgAQQBLAHgAcABRAD0APQA8AC8ASwBJAEQAPgA8AEwAQQBfAFUAUgBMAD4AaAB0AHQAcAA6AC8ALwBwAHIALQBrAGUAeQBvAHMALgBsAGkAYwBlAG4AcwBlAGsAZQB5AHMAZQByAHYAZQByAC4AYwBvAG0ALwBjAG8AcgBlAC8AcgBpAGcAaAB0AHMAbQBhAG4AYQBnAGUAcgAuAGEAcwBtAHgAPAAvAEwAQQBfAFUAUgBMAD4APABEAFMAXwBJAEQAPgBWAGwAUgA3AEkAZABzAEkASgBFAHUAUgBkADAANgBMAGEAcQBzADIAagB3AD0APQA8AC8ARABTAF8ASQBEAD4APABDAFUAUwBUAE8ATQBBAFQAVABSAEkAQgBVAFQARQBTACAAeABtAGwAbgBzAD0AIgAiAD4APABDAEkARAA+AHYAOAAyAHIAcwBHAGwANQBOADAATwB1AEsAOAByAE8ASABBAEsAeABwAFEAPQA9ADwALwBDAEkARAA+ADwARABSAE0AVABZAFAARQA+AHMAbQBvAG8AdABoADwALwBEAFIATQBUAFkAUABFAD4APAAvAEMAVQBTAFQATwBNAEEAVABUAFIASQBCAFUAVABFAFMAPgA8AEMASABFAEMASwBTAFUATQA+ADgARQBLAEQAcQBJAHgAUwAwAFEAWQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA==",
"pssh-hex": "000003e270737368000000009a04f07998404286ab92e65be0885f95000003c2c203000001000100b8033c00570052004d00480045004100440045005200200078006d006c006e0073003d00220068007400740070003a002f002f0073006300680065006d00610073002e006d006900630072006f0073006f00660074002e0063006f006d002f00440052004d002f0032003000300037002f00300033002f0050006c00610079005200650061006400790048006500610064006500720022002000760065007200730069006f006e003d00220034002e0030002e0030002e00300022003e003c0044004100540041003e003c00500052004f00540045004300540049004e0046004f003e003c004b00450059004c0045004e003e00310036003c002f004b00450059004c0045004e003e003c0041004c004700490044003e004100450053004300540052003c002f0041004c004700490044003e003c002f00500052004f00540045004300540049004e0046004f003e003c004b00490044003e007600380032007200730047006c0035004e0030004f0075004b00380072004f00480041004b007800700051003d003d003c002f004b00490044003e003c004c0041005f00550052004c003e0068007400740070003a002f002f00700072002d006b00650079006f0073002e006c006900630065006e00730065006b00650079007300650072007600650072002e0063006f006d002f0063006f00720065002f007200690067006800740073006d0061006e0061006700650072002e00610073006d0078003c002f004c0041005f00550052004c003e003c00440053005f00490044003e0056006c005200370049006400730049004a004500750052006400300036004c0061007100730032006a0077003d003d003c002f00440053005f00490044003e003c0043005500530054004f004d004100540054005200490042005500540045005300200078006d006c006e0073003d00220022003e003c004300490044003e007600380032007200730047006c0035004e0030004f0075004b00380072004f00480041004b007800700051003d003d003c002f004300490044003e003c00440052004d0054005900500045003e0073006d006f006f00740068003c002f00440052004d0054005900500045003e003c002f0043005500530054004f004d0041005400540052004900420055005400450053003e003c0043004800450043004b00530055004d003e00380045004b00440071004900780053003000510059003d003c002f0043004800450043004b00530055004d003e003c002f0044004100540041003e003c002f00570052004d004800450041004400450052003e00"
}
I use mspr:pro tag in the manifest.
As far as I understand, when using mspr:pro , you enter PlayReady Object not PSSH-Box ( for PSSH-BOX cenc:ppsh tag using in manifest ).
How can I build Playready Object from PSSH ?
Just strip the PSSH box header.
PSSH box syntax:
aligned(8) class ProtectionSystemSpecificHeaderBox extends FullBox(‘pssh’, version, flags=0)
{
unsigned int(8)[16] SystemID;
if (version > 0)
{
unsigned int(32) KID_count;
{
unsigned int(8)[16] KID;
} [KID_count]
}
unsigned int(32) DataSize; unsigned
int(8)[DataSize] Data;
}
PSSH hex from your example:
// PSSH, big endian
00 00 03 E2 70 73 73 68 // box header, 994 bytes "pssh"
00 00 00 00 // full box header, version 0, flags 0
9A 04 F0 79 98 40 42 86 AB 92 E6 5B E0 88 5F 95 // PlayReady system ID
00 00 03 C2 // data size, 962 bytes
// PlayReady Object, little-endian
C2 03 00 00 // object length, 962 bytes
01 00 // record count, 1
01 00 // record type, 1 - PRH
B8 03 // record length, 952 bytes
3C 00 57 00 52 [...] // record value, "<WRMHEADER xmlns=..."
You can also decode this online using: https://tools.axinom.com/decoders/PsshBox
Reference:
ISO/IEC 23001-7
PlayReady Header Specification

Nodejs WebSocket response is encrypted or not readable (connecting to a exchange socket)

I am trying to make a request to a WebSocket of a crypto-exchange to get live market data for analysis.
In the Browser the data is shown in readable Text as it is used to populate the orderbook.
When trying to connect to it via nodejs I am getting a hex code that when converted still doesn't make sense.
const WebSocket = require('ws');
const sendData = '{"method":"deals.subscribe","params":["ETHBTC"],"id":18}'
// Establish a WebSocket connection to the echo server
const ws = new WebSocket('wss://ws.exchnageAddres.com');
ws.addEventListener('open', () => {
console.log('Sending:', sendData);
// Send message to the WebSocket server
ws.send(sendData);
});
ws.addEventListener('message', event => {
console.log('Received:', event.data);
});
Response:
Received: <Buffer 1f 8b 08 00 00 00 00 00 00 03 ab 56 4a 2d 2a ca 2f 52 b2 52 c8 2b cd c9 d1 51 50 2a 4a 2d 2e cd 29 01 f2 ab 95 8a 4b 12 4b 4a 8b 81 4c a5 e2 d2 e4 e4 ... 23 more bytes>
Received: <Buffer 1f 8b 08 00 00 00 00 00 00 03 9d 9a df 8a 5c 47 0e c6 5f 25 cc 75 28 24 95 a4 52 ed 65 96 85 7d 80 dc 85 5c 78 d7 86 35 d8 89 89 ed 8b 10 f2 ee fb 95 ... 2012 more bytes>
Received: <Buffer 1f 8b 08 00 00 00 00 00 00 03 55 8c b1 0a 83 30 14 45 7f 45 de 5c 42 e2 6b 92 da d1 52 e8 07 b8 89 43 da 04 2a 18 0d 26 19 44 fc f7 e6 15 3a 74 3d f7 ... 106 more bytes>
How can I connect to the ws in node?
Do I have to use a certificate or anything? Would be awesome if someone could help me out here.
Testing the connection on a chrome extension is giving me a Blob object but I can't really convert that to an array.
Using Burp Decoder works but only there.
Thanks and best regards.

Exif TIFF field offset doesn't point to correct value

I'm trying to extract the DateTime from a JPEG file's Exif header. I did a quick hex dump to try and locate the Tiff entry. Here's a snippet of the hex dump:
00000000 ff d8 ff e1 27 19 45 78 69 66 00 00 4d 4d 00 2a |....'.Exif..MM.*|
00000010 00 00 00 08 00 0b 01 0f 00 02 00 00 00 06 00 00 |................|
.
.
00000060 00 02 00 00 00 05 00 00 00 b6 01 32 00 02 00 00 |...........2....|
00000070 00 14 00 00 00 bc 02 13 00 03 00 00 00 01 00 01 |................|
.
.
000000b0 78 00 00 00 00 48 00 00 00 01 00 00 00 48 00 00 |x....H.......H..|
000000c0 00 01 31 32 2e 32 00 00 32 30 31 39 3a 30 35 3a |..12.2..2019:05:|
000000d0 31 32 20 31 32 3a 30 32 3a 35 38 00 00 20 82 9a |12 12:02:58.. ..|
So from the hex dump, I know that:
The image is "Motorola" type byte aligned because of (0x4d4d)
The tag is DateTime 0x0132 (address 0x006a to 0x006b)
The tag type is 0x0002 which represents ascii string type (address 0x006c to 0x006d)
The number of components is 0x00000014 which is 20 in decimal(address 0x006e to 0x0071)
The value field, which is the offset to the actual value in this case, is 0x000000bc (address 0x0072 to 0x0075).
Now, if I look at the 20 bytes of value starting from address 0x00bc, it starts off with 0x00, 0x48, 0x00, 0x00, which doesn't represent anything. And it gets cut off at address 0xcf which doesn't include the entire date string. And as you can probably see, the actual date value starts at address 0x00c8 with bytes 0x32 0x30 0x31 0x39 0x3a, which is "2019:" and should continue until address 0xdb.
Can anyone explain why this is happening??
the address of any pointer calculate with base+offset and the base in this case is 0x0C because TIFF header start at 0x0C so 0xBC+0x0C=0xC8 that point to Date, also consider that the end of Date has 0x00 so total length is 20.
you can read more about it at this site.

publicEncrypt from crypto module, with RSA_PKCS1_PADDING, might return 255 bytes instead of 256

A project I work on uses the crypto module publicEncrypt function to encrypt some 32 bytes long session keys.
Due to a compatibility issue with the node-forge library we realized that, about once in a hundered iterations, the output of the publicEncrypt is 255 bytes long instead of 256.
We verified this behavior in Chrome, Firefox, and Opera, however we could not replicate the issue in a unit test (using Jest), because in this setting the output of publicEncrypt is consistently 256 bytes long.
Is this an expected behavior of the crypto module? By checking the RFC https://www.rfc-editor.org/rfc/rfc8017#page-28 this seems to be a bug to me.
Below the public key used in our tests and the unit test to illustrate the issue. To clarify, the unit test succeeeds in Jest, but calls to function publicCipher done within a browser sometimes create a 255 bytes long encrypted output.
Key Algorithm: RSA
Key Parameters: 05 00
Key Size: 2048
Key SHA1 Fingerprint: 89 BD 3D 96 DA 7E 65 60 DE B5 C2 33 5D 22 89 95 F0 44 90 EB
Public Key: 30 82 01 0A 02 82 01 01 00 AA 20 54 0F A4 1C 2A B3 BA FA C2 FB B3 C3 17 53 A0 3F C8 AB 7F 22 E0 60 E6 0A AD 80 0D EC 07 C7 FD E3 4A CD 5C 77 BC 0E FE 63 9F 6D 40 6B 21 84 20 2E F9 C4 6D 93 01 E4 CB EB D0 A5 C2 F5 F5 4F C4 F2 9E D8 C7 F5 2A C4 F2 D8 2D 87 A9 18 2B 6D B3 E2 04 EA 7B A6 5D 4A 55 1A 6D C9 1A E1 AF 4B 0C E1 FD 43 74 37 5B 1A 70 11 86 E7 E4 40 DD 6B 27 7C 72 C5 D0 15 79 B0 6D BC 07 F1 43 C7 BF D3 13 EC 94 83 D3 77 44 7B 58 2E 37 82 22 AC 07 7E 61 5F 7D A7 57 09 6C DB 24 24 5D 10 ED 83 DC AE 35 CE 6C 1E AB C2 9E 3A 1D 99 01 F9 0E 2C 6B A4 74 E0 87 1E 86 04 BC 72 A3 3E CF 46 76 57 AC 78 EC 41 AD 2D 82 E5 F5 A8 76 9D 25 0A 87 D8 D4 74 FA 64 9D 14 BF F4 17 B5 CF 2E D7 FF 71 41 94 5D 30 56 F0 17 9C ED 2F CB 66 D3 E5 7F 99 F9 31 42 EE DE 16 AE ED 38 BD E6 9A DD A6 50 75 30 5B D5 02 03 01 00 01
import { publicEncrypt, randomBytes } from 'crypto'
import constants from 'constants'
describe('Encryption output size test.', () => {
const publicKeyPem = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqiBUD6QcKrO6+sL7s8MX
U6A/yKt/IuBg5gqtgA3sB8f940rNXHe8Dv5jn21AayGEIC75xG2TAeTL69ClwvX1
T8TyntjH9SrE8tgth6kYK22z4gTqe6ZdSlUabcka4a9LDOH9Q3Q3WxpwEYbn5EDd
ayd8csXQFXmwbbwH8UPHv9MT7JSD03dEe1guN4IirAd+YV99p1cJbNskJF0Q7YPc
rjXObB6rwp46HZkB+Q4sa6R04IcehgS8cqM+z0Z2V6x47EGtLYLl9ah2nSUKh9jU
dPpknRS/9Be1zy7X/3FBlF0wVvAXnO0vy2bT5X+Z+TFC7t4Wru04veaa3aZQdTBb
1QIDAQAB
-----END PUBLIC KEY-----
`
it('Should create encrypted keys of 256 bytes.', (done) => {
for (let i = 0; i < 1000; i++) {
expect(publicCipher(publicKeyPem, randomBytes(32)).length).toEqual(256)
}
done()
})
})
function publicCipher(publicKeyPem: string, clearText: Buffer): Buffer {
return publicEncrypt({ key: publicKeyPem, padding: constants.RSA_PKCS1_PADDING }, clearText)
}
Update: the issue is due to the removal of leftmost 0 bytes.
I will try find a way to make this issue reproducible, meanwhile I think the following unit test should clarify what is happening (the key pair is self signed and used for testing purposes only, so I have no problem publishing the private key):
import forge from 'node-forge'
import { privateDecrypt } from 'crypto'
import * as constants from 'constants'
it('buggy encrypted random bits from crypto', (done) => {
const encryptedRandomBits = 'inYgmlfL4y0ab5tplmDKCeP0p7q2lcnMqUDjfQpUjqFJkiqoVXQ9A8pA8hyWBf2onea/+iVMtU/Xj9IyLvPQiLkUE9OWptzmwTqnXzzG3ulXUIjud+rpvJdENSJzsX7IwiNaAPWo3EmM57B/fdXaPPGZME203SDPRVWst2XZw7zBfeM2XmS4nSMvs7NM7rGR/Ti3Hb+p7D+PJZUm7oi3npFZHSS1C/SsAXUaAja3HPaXuve+VZfclqrSbQ2P+45cRyQpvcf+ueXqdk/Yqg/sOuufR8eFDyDgRudzMOzLuH6rzrNKYtMXpD9ueFWFRh0G2wOlXNc/acbv0nSN5Dvu'
const publicKeyPem = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqiBUD6QcKrO6+sL7s8MX
U6A/yKt/IuBg5gqtgA3sB8f940rNXHe8Dv5jn21AayGEIC75xG2TAeTL69ClwvX1
T8TyntjH9SrE8tgth6kYK22z4gTqe6ZdSlUabcka4a9LDOH9Q3Q3WxpwEYbn5EDd
ayd8csXQFXmwbbwH8UPHv9MT7JSD03dEe1guN4IirAd+YV99p1cJbNskJF0Q7YPc
rjXObB6rwp46HZkB+Q4sa6R04IcehgS8cqM+z0Z2V6x47EGtLYLl9ah2nSUKh9jU
dPpknRS/9Be1zy7X/3FBlF0wVvAXnO0vy2bT5X+Z+TFC7t4Wru04veaa3aZQdTBb
1QIDAQAB
-----END PUBLIC KEY-----
`
const privateKeyPem = `-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAqiBUD6QcKrO6+sL7s8MXU6A/yKt/IuBg5gqtgA3sB8f940rN
XHe8Dv5jn21AayGEIC75xG2TAeTL69ClwvX1T8TyntjH9SrE8tgth6kYK22z4gTq
e6ZdSlUabcka4a9LDOH9Q3Q3WxpwEYbn5EDdayd8csXQFXmwbbwH8UPHv9MT7JSD
03dEe1guN4IirAd+YV99p1cJbNskJF0Q7YPcrjXObB6rwp46HZkB+Q4sa6R04Ice
hgS8cqM+z0Z2V6x47EGtLYLl9ah2nSUKh9jUdPpknRS/9Be1zy7X/3FBlF0wVvAX
nO0vy2bT5X+Z+TFC7t4Wru04veaa3aZQdTBb1QIDAQABAoIBAAEK0KkF3txOHJOj
tSoNRGvRPALNNiqvCDjwkM6Lh0om6gHF+Asceqz21wJnh3EAlBAkaYhQCYoF7k/k
B9fxbM7PzJK3jkYMvIcmVuURXqIJeoQkdpFKXCDz84T/qef/DG0oR0ZuBFbNCym4
U1xdH14kMEl9t8Ah7jhF4iCSwzsEG/YUU2czCkHwnFaALsnTk6sXhcUvy8BFelIP
TU3QWxMIv2hmEJcn8GXXtORKtirpvU7WlvGSOFwKbd5yxM0oZh5ZneR2oXL/4lre
fP+jQAuAAftfMzvo4EjR/6DaHpg+YWMJMM0sncu6FwFLo0V1l8gdaiPiWRZXkTVq
aujZg9ECgYEA5Xkw2rBMWyLYVm+DgjZ2mhbRop2lWrjGKh8CYFuHXP1C1TRvUsGA
zpNyF4Gz9OAPsUm7JoG3dChr2+/or2UGrhD2BuSDPz9XIhQkQ+SOuBKTV3EcZVDz
BKajm7M+EkdVQdD8Rv5gKTHlTNtGSK+WxmSbjobCVZtjlmWDUm7DwykCgYEAvcrg
pKh20H3iLSZY+6GlngvyXe7fT6gj5t5hylHOBkwAZnlgSoRxjNWkYBsm6lCpWGvS
zYNmgxo2KyjsH59P25gyTzNOIgGpabvK+3qkiO/rDErHMM3K+/PCvYI9Ggc6idWa
p0LJniG1WD+xJTsGaFKpqXDczGDmIiEFxhBa9M0CgYAOIbyEez74jdjM2ek7Z6c+
LhGS9ipsv9xUU7yNupVHgMFQ5/3DFu+byTDJic9PUU0mGehQosRtft/Fl6y4wHv8
1EaSfhgnGPuAucTR+Y1ggKRaSjj5dFbC/pAs0okMDyCNARXIOXoqj0wTw508dLPQ
W/nIeTwWkY88f9vqg6/CoQKBgG/NKRQWIRekcC4EnvpsOLGne/iVlHrKI4wGiDi0
g9b1wm6bJXwAFRvPZmsu03fIWFm7+owR0bt9H1fBXYcrQ9GqEEjTgj1KGVAtzd7i
WjZIjn/JNRmswNw2tgsIw5GnnHZBnD7Xewlp9fesXV//K0EdINCtqYPDuQ11wn7w
d4QpAoGBAJoESzi2a+kQhIoqF+sdCWRXmtieUBvQMFqoIrIYuWMHmbUBewTByRzJ
2LAet1kkPQEScWX3OifuzScuQ2E+UB6q4JFqie+VjFItJU5OE4/45nf6IYyVBxwj
TcZR1bO+Rx1eFnj0Xyhq4Zy9iuGzJhZxpzD7P+LJG9t3rlAkOIyL
-----END RSA PRIVATE KEY-----`
const decryptedWithCrypto = privateDecrypt (
{ key: privateKeyPem, padding: constants.RSA_PKCS1_PADDING },
Buffer.from(encryptedRandomBits, 'base64')
)
const nodePrivateKey = forge.pki.privateKeyFromPem(privateKeyPem) as forge.pki.rsa.PrivateKey
const padding = Buffer.alloc(1)
padding.writeUInt8(0,0)
const padded = Buffer.concat( [ padding, Buffer.from(encryptedRandomBits, 'base64') ])
//node-forge cannot decrypt without the padding!
const decryptedFromPaddedWithNodeForge: string = nodePrivateKey.decrypt(forge.util.decode64(padded.toString('base64')))
const decryptedFromPaddedWithCrypto = privateDecrypt (
{ key: privateKeyPem, padding: constants.RSA_PKCS1_PADDING }, padded
)
expect(btoa(decryptedFromPaddedWithNodeForge)).toEqual(decryptedWithCrypto.toString('base64'))
expect(btoa(decryptedFromPaddedWithNodeForge)).toEqual(decryptedFromPaddedWithCrypto.toString('base64'))
done()
})

Resources