How to encrypt the .wky file outside of the Nitrokey HSM

Hi All,

I have managed to export the .wky wrapped keyfiles with the encrypted privatekey, the “Private Key Description” and the corresponding x509 certificate.

How can I decrypt the .wky file? once I have a copy on my local system?

Regards

The DKEK class located in scsh/sc-hsm/DKEK.js can encode and decode the .wky format. You could write a small Smart Card Shell script to automate that.

1 Like

Thank you so much for you reply.

Are you able to provide the exact command that needs to be run to decode a .wky please?

The use case is that I have exported a privatekey/certificate from the Nitrokey and now its on my locate machine in .wky format.

Apologies for asking a trivial question? I am new to this and really appreciate any support you can offer.

Regards
Wajid

Thank you SC-HSM

I have been provided the following: Any Idea how I am execute this to decrypt a .wky file.

Thank you so much and sorry for the noddy question.

—8<------8<------8<------8<------8<------8<------8<------8<—
var File = require(“scsh/file/File”).File;
var DKEK = require(“scsh/sc-hsm/DKEK”).DKEK;

var fn = GPSystem.mapFilename(“rsa.wky”);
var f = new File(fn);
var bin = f.readAllAsBinary();
var a = new ASN1(bin);
var blob = a.get(0).value;

var fn = GPSystem.mapFilename(“password.pbe”);
var f = new File(fn);
var bin = f.readAllAsBinary();

var share = DKEK.decryptKeyShare(bin, new ByteString(“password”, ASCII));

var crypto = new Crypto();
var dkek = new DKEK(crypto);
dkek.importDKEKShare(share);
dkek.dumpKeyBLOB(blob);
—8<------8<------8<------8<------8<------8<------8<------8<—

1 Like

Save to a file and run it from the Smart Card Shell.

Thanks sc-hsm (you are very helpful)

I have tried the below but it didn’t work. Can you please let me know what file type I need to save the file as? and how do i run it from Smart Card Shell.

I saved the file as a .js file and click on File > Run Script on the Smart Card Shell but got the following error:
GPError: GPSystem (INVALID_TYPE/0) - “Expected string argument” in C:\Program Files\CardContact\scsh3\scsh\file\File.js#62

I also saved the file as a .java and click on File > Run Script and got the same error.

var File = require(“scsh/file/File”).File;
var DKEK = require(“scsh/sc-hsm/DKEK”).DKEK;

var fn = GPSystem.mapFilename(“rsa.wky”);
var f = new File(fn);
var bin = f.readAllAsBinary();
var a = new ASN1(bin);
var blob = a.get(0).value;

var fn = GPSystem.mapFilename(“password.pbe”);
var f = new File(fn);
var bin = f.readAllAsBinary();

var share = DKEK.decryptKeyShare(bin, new ByteString(“password”, ASCII));

var crypto = new Crypto();
var dkek = new DKEK(crypto);
dkek.importDKEKShare(share);
dkek.dumpKeyBLOB(blob);

Thank YOU so much

Regards

File ending should be ideally .js. You need to replace the exemplary file names (e.g. rsa.wky, password.pbe) with true file names.

Thanks Jan,
Quick update I have managed to export the key blob with the data that you provided which is great step forward.

Thank you for your assistance however I need to have the private key exported/formatted to base64 for example:

-----BEGIN PRIVATE KEY-----
MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAAcEJzAlAgEBBCAOlqNS8o2wpm054O0+
Wwb89gdNVeC6lztrhyvCZzSEKQ==
-----END PRIVATE KEY-----

At presented I am present with the below; Is there an easy way I can update the .js script to output the private key in the format above.

Values from key blob:

Checking the MAC : Passed
KCV : 268138D870E05463 [Must match the KCV of the DKEK for import]
Key type : 12 [5=RSA, 6=RSA-CRT, 12=ECC, 15=AES]
Default Algorithm ID : 0.4.0.127.0.7.2.2.2.2.3 (10) [Default algorithm]
Allowed Algorithm IDs : (0)
Access Conditions : (0) [Not used]
Key OID : (0) [Not used]
Randomize : 3A738AADAA1FA532 [Random data prepended at export]
Key size : 256 [Key size in bits (ECC/RSA) or bytes (AES)]
A : FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC (32)
B : 5AC635D8AA3A93E3B3EBBD55769886BC651D06B0CC53B0F63CCE3C3E27D2604B (32)
Prime factor P : FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF (32)
Order : FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84E3B9CAC2FC632551 (32)
Generator G : 046B17D1F2E12C4247F8BCE6E533A440F277037C812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5 (65)
Secret D : 0E96A352F28DB0A66D39E0ED3E5B06FCD6074D55E07A973B6B872BC267348429 (32)
Public Point Q : 046F40C5F5D3560CF295ECE1F0342919738B539F912A70D7BD3F9A60CEA4F2A29E5EAB542EB2EE3A47ECD2AEFA48C822837DCE543D07211796289FEE45C65E7ED2 (65)

Hey crypto-user,

using the following lines of python I can generate the private key in PEM format as you described:

from Crypto.PublicKey import ECC

# this one is taken from your post "Secret D" 
s_hex = "0E96A352F28DB0A66D39E0ED3E5B06FCD6074D55E07A973B6B872BC267348429"

s_bin = bytes.fromhex(s_hex)
s = int.from_bytes(s_bin, 'big', signed=False)
# "s" is the actual "secret" as integer now 

priv_key = ECC.construct(curve="secp256r1", d=s)
print(priv_key.export_key(format="PEM"))

the last line will then generate/output:

-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgDpajUvKNsKZtOeDt
PlsG/NYHTVXgepc7a4crwmc0hCmhRANCAASZzlwg9AdgBGDbHXFqBOCGT0AD4yZS
qasJkC4YgnRRXNR2NQkkXVw2b3vj0V2WarpKhlu6OlgsEjFEmmwmRNsi
-----END PRIVATE KEY-----

is this what you are looking for?

edit: the actual curve might not be the correct one, took secp256r1 here

Hi, I have not managed to run the above python due to missing pre-requisites.
We are using the following private key settings. Is it at all possible for you to provided a standalone tool with dependence that can perform this conversion from the HEX to PEM?

Private-Key: (256 bit)
ASN1 OID: prime256v1
NIST CURVE: P-256

Jan, daringer

Can you please provided a way of doing this move from HEX to PEM with JS. Perhaps something like this https://github.com/indutny/elliptic/issues/43

Hi Daringer, Jan,

Our requirement is to have a DKEK share greater then 1. For example 3 of 3 can you please help with updated code before that supports multiple password.pbe files and passwords? thank you

var File = require(“scsh/file/File”).File;
var DKEK = require(“scsh/sc-hsm/DKEK”).DKEK;

var fn = GPSystem.mapFilename(“rsa.wky”);
var f = new File(fn);
var bin = f.readAllAsBinary();
var a = new ASN1(bin);
var blob = a.get(0).value;

var fn = GPSystem.mapFilename(“password.pbe”);
var f = new File(fn);
var bin = f.readAllAsBinary();

var share = DKEK.decryptKeyShare(bin, new ByteString(“password”, ASCII));

var crypto = new Crypto();
var dkek = new DKEK(crypto);
dkek.importDKEKShare(share);
dkek.dumpKeyBLOB(blob);

Thank YOU so much

Regards

to make the python code run, you just have to install “pycryptodome” using your package manager or pip like this:

$ sudo pip3 install pycryptodome

(your distribution might not need sudo)
if you are looking for JS code, then it looks like your found the solution already: https://github.com/indutny/elliptic/issues/43#issuecomment-246187162

just fill in rawPrivateKey with your private (raw) hex key should do the job. Both the python code and the JS example already use the right curve: prime256v1

to finally export using node-crypto please refer to: https://nodejs.org/api/crypto.html#crypto_keyobject_export_options

should be something like:

ellipticKey.export({type: "sec1", format: "pem"})

Hi Daringer,

Thank you that’s is very help.

As per my previous message our requirement is to have a DKEK share greater then 1. For example 3 of 3 DKEK shares - can you please help with updated code that supports multiple password.pbe files and passwords? thank you

var File = require(“scsh/file/File”).File;
var DKEK = require(“scsh/sc-hsm/DKEK”).DKEK;

var fn = GPSystem.mapFilename(“rsa.wky”);
var f = new File(fn);
var bin = f.readAllAsBinary();
var a = new ASN1(bin);
var blob = a.get(0).value;

var fn = GPSystem.mapFilename(“password.pbe”);
var f = new File(fn);
var bin = f.readAllAsBinary();

var share = DKEK.decryptKeyShare(bin, new ByteString(“password”, ASCII));

var crypto = new Crypto();
var dkek = new DKEK(crypto);
dkek.importDKEKShare(share);
dkek.dumpKeyBLOB(blob);
[/quote]

hey crypto-user,

I am sorry, but I cannot really help you with sc-hsm implementation, simply have no experience here.
Overall from conceptional point of view, I guess you would have to ensure that the DKEK KeyShare is already setup using 3 different pbe-files. Then the process of unlocking should be similar to what you pasted with a changed password.pbe and their respective “password”.

cheers

Hi Daringer,

My query is not with sc-hsm. I was provided the code below to be able to unencrypt a .wky private key. This works fine when we have one DKEK share. however when a .wky has a quorum of 3 and there are 3 .pbe files to undecrypt the .wky file it fails

As per my previous message our requirement is to have a DKEK share greater then 1. For example 3 3 DKEK shares - that supports multiple password.pbe files and passwords to undecrypt ? thank you

I have tried to update the code with the following (extra .pbe and passwords entries) but it fails - can you please provide update to the code before that supports multiple DKEK shares (.PBE to decrypt an single .WKY). The original code before was very kindly provided by Jan.

var File = require(“scsh/file/File”).File;
var DKEK = require(“scsh/sc-hsm/DKEK”).DKEK;

var fn = GPSystem.mapFilename(“rsa.wky”);
var f = new File(fn);
var bin = f.readAllAsBinary();
var a = new ASN1(bin);
var blob = a.get(0).value;

var fn = GPSystem.mapFilename(“password1.pbe”, “password2.pbe” “password3.pbe”);
var f = new File(fn);
var bin = f.readAllAsBinary();

var share = DKEK.decryptKeyShare(bin, new ByteString(“password1”, “password2”, “password3”, ASCII));

var crypto = new Crypto();
var dkek = new DKEK(crypto);
dkek.importDKEKShare(share);
dkek.dumpKeyBLOB(blob);