Generating PEM code from DER code for RSA public key - base64

I have asn.1 code
RSAPublicKey ::= SEQUENCE {
modulus INTEGER, 7120255303029382831
publicExponent INTEGER 4242026487
}
I encoded asn.1 code with DER
30 11 02 08 62 D0 3A 79 2F 28 5E AF 02 05 00 FC D8 02 FF 07
I encoded DER code with base64(I'm trying to generate PEM code)
MzAgMTEgMDIgMDggNjIgRDAgM0EgNzkgMkYgMjggNUUgQUYgMDIgMDUgMDAgRkMgRDggMDIgRkYgMDc
But when I try to encrypt something with it it says 'Error: Too few bytes to read ASN.1 value.' in cyberchef.
What should I do please help me with how it.

Related

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 RSA prehashed sign

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

How to get CRC algorithm by result

how can I guess CRC algorithm by having some examples(line -> result). It`s 1 byte result. Seems like standard 1 byte CRC is not working here.
Examples are in hex
02 08 00 3E 00 00 -> 34
02 0C 00 3E FF 01 03 9F 1A 00 -> 48
P.S. This is Saturn NFC reader exchange. I can`t find the guide to get algorithm.

How to generate an ECDSA sign without need of PEM key format in NodeJS?

I have to generate an ECDSA sign and decode it after.
I tried with two different forms: one gave me a sign of size 135, while the other gave me a sign with size 70. The first one was generated with a pem key (with asn1js and bn modules as the answer in this link) and the second was generated with 'raw' key (eccrypto module), as we can seen below:
const ecdsa = require('eccrypto');
shaMsg = crypto.createHash('sha256').update(myData).digest();
ecdsa.sign(privateKey, shaMsg).then(function(sig) {
console.log("Signature in DER format:", sig, '-------size: ', sig.length);
ecdsa.verify(publicKey(), msg, sig).then(function() {
console.log("Signature is OK");
}).catch(function() {
console.log("Signature is BAD");
});
});
The output for this code is:
Signature in DER format: < Buffer 30 44 02 20 56 5c 61 76 a7 17 3c 67 8d 04 54 dd d5 9a 81 3a e9 1f af a6 7e 2d 34 3e 78 78 47 fb 5e 8e 9c 79 02 20 78 a4 bb f6 20 41 7c 8c 59 1b 93 43 ... > -------size: 70
I need to decode my sign to make other operations. Can anyone help me with this?
As nobody helped, I did what I wanted with another module (elliptic):
var EC = require("elliptic").ec;
var ec = new EC("secp256k1");
var shaMsg = crypto.createHash("sha256").update(myData.toString()).digest();
var mySign = ec.sign(shaMsg, privateKey, {canonical: true});
I hope this helps someone else.

Error 0x6700 in securechannel.processSecurity(apdu)

I want to generate gp secure channel 01. my trace is:
Send: 80 50 00 00 08 00 00 00 00 00 00 00 00
Recv: 00 00 00 00 00 00 00 00 00 00 FF 02 00 02 0E 5A 8F F4 57 DD 35 5C 49 A6 8B 15 E9 A5 9000
so I have :
Card challenge= 00 02 0E 5A 8F F4 57 DD
Host challenge=00 00 00 00 00 00 00 00
according SPC01: image
Derivation data== 8F F4 57 DD 00 00 00 00 00 02 0E 5A 00 00 00 00
IV=0000000000000000
c_ENC: 404142434445464748494A4B4C4D4E4F
according this image and 3Des online
session s_ENC= C72F032C8BAD55D4D2579295CCF0A6CA
now :
hot-auth_data = card challenge + host challenge + pad
host-auth= 00020E5A8FF457DD00000000000000008000000000000000
s_ENC=C72F032C8BAD55D4D2579295CCF0A6CA
IV=0000000000000000
===========
result= 93CC77E144488A031BFFCCC62EB3B5C233A485F8255FE90E
Host cryptogram= 33A485F8255FE90E
but when I send :
848200000833A485F8255FE90E
I have error 0x6700 in method SDInstruction in line
short len = sc.processSecurity(apdu);
public void process(APDU apdu) throws ISOException {
if (selectingApplet()) {
return;
}
byte[] buffer = apdu.getBuffer();
switch (buffer[ISO7816.OFFSET_INS]) {
case ISO7816.INS_SELECT:
select();
return;
case INS_INIT_UPDATE:
case INS_EXT_AUTH:
SDInstruction(apdu);
break;
}
}
private void SDInstruction(APDU apdu)
{
byte[] buf = apdu.getBuffer();
byte cla = buf[ISO7816.OFFSET_CLA];
byte ins = buf[ISO7816.OFFSET_INS];
apdu.setIncomingAndReceive();
if(ins == INS_INIT_UPDATE)
sc = GPSystem.getSecureChannel();
short len = sc.processSecurity(apdu);
apdu.setOutgoing();
apdu.setOutgoingLength(len);
apdu.sendBytes(ISO7816.OFFSET_CDATA, (short) len);
}
Your card is using SCP02 and not SCP01.
Given the response to the INITIALIZE UPDATE command:
00 00 00 00 00 00 00 00 00 00 FF 02 00 02 0E 5A 8F F4 57 DD 35 5C 49 A6 8B 15 E9 A5 9000
The highlighted part is the "Key Information" which contains:
"Key Version Number" -- in your trace 0xFF
"Secure Channel Protocol Identifier" -- in your trace it is 0x02 indicating SCP02
See the Global Platform Card Specification for further reference (sections describing the INITIALIZE UPDATE command).
So you need to establish the secure channel with the card according to the SCP02.
Some additional (random) notes:
be sure to check the "i" secure channel parameter encoded inside the "Card Recognition Data" (tag '64') as well
you might want to look at the method GlobalPlatform.openSecureChannel() and the inner class GlobalPlatform.SCP0102Wrapper in the GlobalPlatformPro tool source code
Good luck!
According to the GlobalPlatform specification, the EXTERNAL AUTHENTICATE command has to include the host cryptogram as well as the MAC. Both are 8 bytes long, hence, your command should be 16 bytes in total.
If you want to implement the generation of this MAC value yourself, you can follow the description in the GlobalPlatform spec. But I suggest you to make use of available open source implementation. For example: GPJ is a Java implementation of the GlobalPlatform specification and has all commands that you need. You can take a look at the class GlobalPlatformService, where you will find the implementation of the secure channel protocol. GPDroid (github.com/mobilesec/secure-element-gpdroid) is a wrapper for this project on Android.

Resources