How to decrypt safeNet wrapped exported keys? - pkcs#11

I have exported a 3DES key from my SafeNet HSM to a file using a tool named KMU. This tool wraps the key before extraction using another 3DES key. I have access to the plain-text value of the second key.
The question is "how can I decrypt the wrapped file to obtain plain-text value of the wrapped key?"
Update:
FYI: The final exported file looks like this:
L1: 000001f4 000001a800000001000001a0
L2: 00000020 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
L3: 00000140 0000001b0000010300000001010100000162000000010101800001290000000101010000016500000001010000000164000000010100000000010000000101010000000200000001010100000170000000010101000000030000000f014949494949494949494949494949490000010c000000010101000001040000000101010000010a000000010101000001060000000101010000010500000001010100000108000000010101000001070000000101018000012b000000010100000001610000000401000000100000000000000004010000000400000100000000040100000014800001030000000000000001020000000000000001100000000000000001110000000000800001280000000101000000016300000001010080000102000000100132303131313232383136323032313030000000000000000000000000
L4: 00000010 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
L5: 00000020 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxx
L6: 00000020 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
L7: 00000020 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
The parts which are 'x' are the data which looks encrypted in the original file and so I replaced them with 'x'. Line numbers, spaces and new-lines are also added by me to make the content more readable!

See chapter "Key Backup Feature Tutorial" in the document Key Management Utility User (KMU) Reference for overall scheme description.
Unfortunately this document has not been updated to the last version of the scheme which uses AES tK and HMAC for M_mK.
As far as I remember it is possible to tell KMU to use the older DES3 scheme with the -3 command line option.
I have a working implementation but unfortunately can not provide the code.
Key restoration steps summary:
Check overall file structure (magic 0x000001f4 | varLen encoded payload | 4 byte MAC | varLen wrapped MAC key | varLen wrapped transport key)
unwrap AES transport key (using the wrap key and it's key type specific algorithm, e.g. CKM_RSA_PKCS)
unwrap generic secret MAC key (using AES transport key and CKM_AES_ECB. Length is 32)
verify MAC of encoded payload (using MAC key with CKM_SHA512_HMAC_GENERAL)
unwrap all backed-up keys from the payload (using AES transport key with CKM_WRAPKEY_AES_CBC and zero IV)
You might want to use PKCS#11 logger library (see PTK-C Programming Guide) and record the activity of the KMU utility during key restore to verify the fine details of the algorithm.
Good luck with your project!
EDIT> Overall structure of file (given your example data):
000001f4 // Magic
000001a8 // Length of encoded payload
00000001 // Number of keys
000001a0 // Wrapped key #1 length
xxxx...xxxx // Wrapped key #1 data for CKM_WRAPKEY_AES_CBC
xxxxxxxx // Payload MAC
00000020 // Wrapped MAC key cryptogram length
xxxx...xxxx // Wrapped MAC key cryptogram
00000020 // Wrapped transport key cryptogram length
xxxx...xxxx // // Wrapped transport key cryptogram
See CKM_WRAPKEY_AES_CBC and CKM_WRAPKEY_DES3_CBC for format used to encode individual exported key data (#1..#n) inside encoded payload.

Related

X509 Decoder tool based on Certificate schema file

I am looking for a tool which is capable to decode X509 Certificated where additional Extensions are also added according to a predefined schema.
Similar to this. I assume if it is the typical notation for the schema, then someone must have implemented a generic parser for that.
FooProtocol DEFINITIONS ::= BEGIN
FooQuestion ::= SEQUENCE {
trackingNumber INTEGER(0..199),
question IA5String
}
FooAnswer ::= SEQUENCE {
questionNumber INTEGER(10..20),
answer BOOLEAN
}
FooHistory ::= SEQUENCE {
questions SEQUENCE(SIZE(0..10)) OF FooQuestion,
answers SEQUENCE(SIZE(1..10)) OF FooAnswer,
anArray SEQUENCE(SIZE(100)) OF INTEGER(0..1000),
...
}
END
or real life example for a given Object ID extension
boot_seq := SEQUENCE
{
certType INTEGER, -- indicates certificate type
bootCore INTEGER, -- indicates the core in the device that needs to be booted
bootCoreOpts INTEGER, -- Configuration options for the core being booted
destAddr OCTET STRING, -- Load address
imageSize INTEGER -- image size
}
Those are the tools that are capable of compiling ASN.1 schemas into data bindings in a variety of languages and platforms: https://www.itu.int/en/ITU-T/asn1/Pages/Tools.aspx
Heimdal in its master branch has an open source ASN.1 compiler that understands a subset of X.681/X.682/X.683 extensions and can actually fully decode a Certificate, including every kind of Attribute, Extension, and OtherName declared in lib/asn1/rfc2459.asn1 (and you can add more, rebuild, and use it).
It also can transliterate DER to JSON (but it's not X.697 JER compliant), so you can run asn1_print /path/to/DER/file Certificate and you'll get a beautiful JSON representation of the complete certificate, including all the attributes, extensions, and otherName SAN types that are declared in lib/asn1/rfc2459.asn1.

Why does Blockcypher signer tool return some extra characters than bip32 dart package?

I'm trying to sign a transaction skeleton Blockcypher returns, in order to send it along, following https://www.blockcypher.com/dev/bitcoin/#creating-transactions.
For this example, I'll use the completely-unsafe 'raw raw raw raw raw raw raw raw raw raw raw raw' mnemonic, which using dart bip32 package creates a BIP32 with private key 0x05a2716a8eb37eb2aaa72594573165349498aa6ca20c71346fb15d82c0cbbf7c and address mpQfiFFq7SHvzS9ebxMRGVohwHTRJJf9ra for BTC testnet.
Blockcypher Tx Skeleton tosign is 1cbbb4d229dcafe6dc3363daab8de99d6d38b043ce62b7129a8236e40053383e.
Using Blockcypher signer tool:
$ ./signer 1cbbb4d229dcafe6dc3363daab8de99d6d38b043ce62b7129a8236e40053383e 05a2716a8eb37eb2aaa72594573165349498aa6ca20c71346fb15d82c0cbbf7c
304402202711792b72547d2a1730a319bd219854f0892451b8bc2ab8c17ec0c6cba4ecc4022058f675ca0af3db455913e59dadc7c5e0bd0bf1b8ef8c13e830a627a18ac375ab
On the other hand, using bip32 I get:
String toSign = txSkel['tosign'][0];
var uToSign = crypto.hexToBytes(toSign);
var signed = fromNode.sign(uToSign);
var signedHex = bufferToHex(signed);
var signedHexNo0x = signedHex.substring(2);
where fromNode is the bip32.BIP32 node. Output is signedHexNo0x = 2711792b72547d2a1730a319bd219854f0892451b8bc2ab8c17ec0c6cba4ecc458f675ca0af3db455913e59dadc7c5e0bd0bf1b8ef8c13e830a627a18ac375ab.
At first sight, they seem completely different buffers, but after a detailed look, Blockcypher signer output only has some extra characters than that of bip32:
Blockcypher signer output (I split it into several lines for you to see it clearly):
30440220
2711792b72547d2a1730a319bd219854f0892451b8bc2ab8c17ec0c6cba4ecc4
0220
58f675ca0af3db455913e59dadc7c5e0bd0bf1b8ef8c13e830a627a18ac375ab
bip32 output (also intentionally split):
2711792b72547d2a1730a319bd219854f0892451b8bc2ab8c17ec0c6cba4ecc4
58f675ca0af3db455913e59dadc7c5e0bd0bf1b8ef8c13e830a627a18ac375ab
I'd expect two 64-character numbers to give a 128-characters signature, which bip32 output accomplishes. Hence, Blockcypher signer output has 140 characters, i.e. 12 more than the former, which is clear when seen as split into lines as above.
I'd be really thankful to anyone throwing some light on this issue, which I need to understand and correct. I need to implement the solution in dart, I cannot use the signer script other than for testing.
The dart bip32 package doesn't seem to encode the signature in DER format, but rather in a simple (r, s) encoding. However DER is required for Bitcoin. For more information see:
https://bitcoin.stackexchange.com/questions/92680/what-are-the-der-signature-and-sec-format
You can either add the DER extra bytes yourself according to your r and s or check if there's a DER encoding in the dart bip32 library.

How to do SSL public key pinning in flutter/dart?

relatively new to Flutter here (and programming in general). Only familiar with the more basic stuffs but I've now encountered the need to use a CertificatePinner such as this in flutter/dart:
https://square.github.io/okhttp/3.x/okhttp/okhttp3/CertificatePinner.html (I've successfully implemented this in my previous kotlin/java project in android studio). My goal is to pin public key (not certificate)
All I have is the public key in the form of a string like shown below, nothing else:
"sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
How do I go about achieving this? I've asked this in an open issue on github but haven't gotten any responses yet (https://github.com/dart-lang/sdk/issues/35981). Hoping someone has managed to achieve this.
I've also scoured through other sources. I think the closest one to a solution for me is How can I do public key pinning in Flutter?
but I don't quite get what is being done there and I can't comment to ask questions there since I don't have enough reputation yet.
For comparison, all I want to do is achieve the same thing in flutter/dart what I could in java/kotlin with these few lines of code:
String hostname = "publicobject.com";
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add(hostname, "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
.build();
Thanks for your help
Start with the code in the answer you refer to. That takes the certificate in DER format and starts decoding it.
ASN1Parser p = ASN1Parser(der);
ASN1Sequence signedCert = p.nextObject() as ASN1Sequence;
ASN1Sequence cert = signedCert.elements[0] as ASN1Sequence;
ASN1Sequence pubKeyElement = cert.elements[6] as ASN1Sequence;
// this is the Subject Public Key element, which describes the type of key and actual value
For example, if we decode the certificate of pub.dev we find that it's an RSA key with a modulus of 65537 and a value of 2347......:
SEQUENCE (2 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER 1.2.840.113549.1.1.1 rsaEncryption (PKCS #1)
NULL
BIT STRING (1 elem)
SEQUENCE (2 elem)
INTEGER (2048 bit) 234782553149463204049153749736864715384123240676730175743244004248041…
INTEGER 65537
From the RFC, the SPKI fingerprint is the SHA-256 hash of this whole element.
// you need to import dart:convert and package:crypto/crypto.dart
var hash = base64.encode(sha256.convert(pubKeyElement.contentBytes()).bytes);
var spkiFingerprint = 'sha256/$hash'; // should match the value you have
Caveats
The badCertificateCallback doesn't deliver the whole certificate chain, so you can't walk up the whole chain. What's worse is that it doesn't always seem to deliver the leaf certificate! Sometimes it delivers an intermediate certificate.

MakeSignature.signDetached throws No Such Algorithm exception (SUN provider & SHA-256)

I am trying to digitally sign a PDF document with iText. Since I will be using a hardware encryptor with JCE provider eventually I am also trying to test getting rid of BountyCastle in my unit test and instead use the default SUN implementation for the time being (until the hardware encryptor arrives).
However, I get the following exception when I run my program:
Exception in thread "main" java.security.NoSuchAlgorithmException: no such algorithm: SHA256 for provider SUN
at sun.security.jca.GetInstance.getService(GetInstance.java:87)
at sun.security.jca.GetInstance.getInstance(GetInstance.java:206)
at java.security.Security.getImpl(Security.java:698)
at java.security.MessageDigest.getInstance(MessageDigest.java:215)
at com.itextpdf.text.pdf.security.DigestAlgorithms.getMessageDigest(DigestAlgorithms.java:159)
at com.itextpdf.text.pdf.security.ProviderDigest.getMessageDigest(ProviderDigest.java:61)
at com.itextpdf.text.pdf.security.MakeSignature.signDetached(MakeSignature.java:130)
at SignDoc.signPdf(SignDoc.java:142)
at SignDoc.main(SignDoc.java:182)
The last few lines of codes are as below:
//ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "BC");
//ExternalDigest digest = new BouncyCastleDigest();
//ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "SUN");
ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "SunRsaSign");
ExternalDigest digest = new ProviderDigest("SUN");
MakeSignature.signDetached(appearance, digest, es, chain, null, null, null, 0, CryptoStandard.CMS);
As you can see, I am just copying the samples and changed the provider name and the call 'new BouncyCastleDigest()' to 'new ProviderDigest("SUN")'
Peeking at the source codes of iText (5.5.1-SNAPSHOT), I find the followings code fragments suspicious:
MakeSignature.java line 142 - 145
hashAlgorithm = externalSignature.getHashAlgorithm() is called and then used in
DigestAlgorithms.digest(data, externalDigest.getMessageDigest(hashAlgorithm));
PrivateKeySignature.java line 76
Since I am using PrivateKeySignature, I peek at PrivateKeySignature.java and find that it returns its private class member hashAlgorithm and this is how it obtains the value during Construction (line 76):
this.hashAlgorithm =
DigestAlgorithms.getDigest(DigestAlgorithms.getAllowedDigests(hashAlgorithm));
DigestAlgorithms.java methods getAllowedDigests() and getDigest()
In turn, getAllowedDigests() returns the OID of the algorithm if the algorithm name is found in the allowedDigests hash map (2.16.840.1.101.3.4.2.1 in my case), otherwise it returns null.
getDigest gets the digest name back from the OID using the digestNames hash map.
However, the name in digestNames hash map that corresponds to the OID is SHA256, not SHA-256.
As a result, the final digest name got was "SHA256" as opposed to "SHA-256" and "SHA256" was causing the NoSuchAlgorithm exception in SUN provider.
(I tried getting a message digest instance directly using the SUN provider. It succeeded for SHA-256 but threw the same exception I am reporting here for SHA256.
Is this a problem with iText when using JCE providers other than BC?
Appreciate if anyone could shed some light on my problem.
As a temporary workaround, I added the followings to PrivateKeySignature.java:
// Temporary fix - to remove hyphenation in hashAlgorithm name
// String signMode = hashAlgorithm + "with" + encryptionAlgorithm;
String signMode = hashAlgorithm.replaceAll("-","") + "with" + encryptionAlgorithm;
// End Temporary fix
It works for me at least for now. Has to investigate how standard names of different algorithms in different context go before a long term solution can be devised, I believe.

Saving/Reading BigInteger RSA keys to/from file

I am trying to implement RSA using Big integers i can currently encrypt and decrypt fine but I need to be able to take the 2 lots of 2 BigIntegers n, e and n, d of any Bit length up to 2048 and then some how save them to files named publicKey.txt and privateKey.txt . and then be able to read it in later. does anyone have any ideas for this.
would like to somehow save them like this so i can separate them into their 2 parts on reading them in using the , as the separator
publicKey.txt
n,e
privateKey.txt
n,d
RSA standard defines ASN.1 encoding for serializing private and public keys for transferring and storage. This format is a standard for cryptography software.