How to get private key with asn format from pfx? - visual-c++

How to get private key with asn format from pfx? I need to get the private key with asn format to put to Qt's variable QSslKey to connect https server.
I have to use Win32 Api to do it, and I can't use OpenSSL to transform it.
First I try to get the private key directly:
1.CertOpenSystemStore(NULL, _T("MY"))
2.CryptAcquireCertificatePrivateKey(...)
3.CryptGetUserKey(...)
4.CryptExportKey(...)
But the private key I have got, I don't know how to use it.

Warning : This is not the exact answer for your question, but i hope it will give you some help towards what you want to acheive
Based on my experience, Windows crypto APIs are designed to use the private key within the certificate store rather than export the key outside, unless you are using CryptoAPI standard functions like PFXExportCertStoreEx ().
CryptExportKey function gives the private/public key pair in a key blob structure which you have to convert to the format you want. The closest thing i have ever seen this being being done is in
Openssl engine for Windows, filename : e_capi.c
refer to the function
**capi_load_privkey() and subfunction capi_get_pkey()**
Here conversion of the Key blob to OpenSSL compatible structure is done.
Hope this helps

Related

Verifyable logfile at customer site

We want to create a logfile at customer site where
the customer is able to read the log (plain text)
we can verify at our site that the log file isn't manipulated
A few hundred bytes of unreadable data is okay. But some customers do not send us files where they can't verify that they do not contain sensible data.
The only reasonable option I see so far is to append a cryptographic checksum (e.g. SHA256(SECRET_VALUE + "logtext")). The SECRET_VALUE would be something hardcoded which is plain "security through obscurity". Is there any better way?
We use the DotNet-library and I do not want to implement any crypto algorithm by hand if that matters.
You can use standard HMAC algorithm with a secret key to perform the checksum.
Using a secret key prevents in a simple way that the checksum can be regenerated directly. A hardcoded key could be extracted from code, but for your use case I think is enough
The result is a binary hash. To insert it into the text file encode the value as hexadecimal or base64, and ensure you are able to revert the process in server side so you can calculate the hash again with the original file.
You could use also a detached hash file to avoid modifying the log file
Target
customer readable logfiles
verifyable by our side
minimum of binary data
must work offline
Options
Public-Private-key-things... (RSA, ...)
would be secure
but only binary data
Add a signature
We are not the first ones with that idea ( https://en.wikipedia.org/wiki/Hash-based_message_authentication_code )
DotNet supports that ( System.Security.Cryptography.HMACSHA256 )
Key must be stored somewhere ... in source
Even with obfuscation: not possible to do so securely
Trusted Timestamping
again: we are not first ( https://en.wikipedia.org/wiki/Trusted_timestamping )
needs connection to "trusted third party" (means: a web service)
Build Hash + TimeStamp -> send to third party -> sign the data (public-private-key stuff) -> send back
Best option so far
Add a signature with HMAC
Store the key in native code (not THAT easy to extract)
Get code obfuscation running and build some extra loops in C#
Every once in a while (5min?) put a signature into log AND into windows application log
application log is at least basically secured against modification (read only)
and it's collected by the our error report
easy to oversee by customer (evil grin)

Append Entry To KeystoreFile

I have an keystore file with AES 256 keys and I would like to increase it. I have the following code:
final KeyStore ks = KeyStore.getInstance(KEY_STORE_TYPE);
ks.load(inputStream, ksPassword);
ks.setEntry(entryName, new KeyStore.SecretKeyEntry(appKey), entryPassword);
ks.store(new FileOutputStream(outputStream, true));
But when I call the store method the new key entry isn't stored on a existing file referenced by my outputStream. Any ideas? Is possible to increment keys on existing keystore file?
There is no concept of increasing Key Size on an existing Key. If you want a Key of different size, you have to create a different Key.
When you are storing a new Key, you might be referring to a different File in your outputstream, that might be the reason it isn't being added to your existing KeyStore.
I found the solution!
When I created the outputStream I created using the StandardOpenOption.APPEND. I changed to StandardOpenOption.TRUNCATE_EXISTING and that works!
Thanks!

How can I import a .pfx file that was created without a password?

I have created a PFX PDU using the java bouncycastle library. Inside the PFX PDU, there are two certificates and two encrypted private keys. All the contents are used as PKCS#7 data content (i.e. no encryption, stored as octet strings).I organised the elements according to the guidelines of PKCS#12 (RFC 7292 Section 5). Then I wrote the DER encoded byte array to a file.
I opened the file in a hex editor and saw that the object structure is OK. I have also read the file contents and built a bouncycastle PFX object from it. But when I try to open the .pfx file from my file system, the Certificate Import Wizard asks for the password for the private key. I did not use any password to create the PFX object. I have tried to use empty string and the password used for encrypting the private keys, but they didn't work. It shows "The password you entered is incorrect.".
Is there something I missed here? How can I get the password required to import certificates?
In RFC 7292, section 4.1, page 41, details of AuthenticatedSafe is described. AutthenticatedSafe is sequence OF ContentInfo which could one of three types.
AuthenticatedSafe ::= SEQUENCE OF ContentInfo
-- Data if unencrypted
-- EncryptedData if password-encrypted
-- EnvelopedData if public key-encrypted
Make your authenticatedSafe data as EncryptedData where you needs to encrypt the BERencoded value of AuthenticatedSafe with the SecretKey generated from password you will give using SecretKeyFactory and PBEParameterSpec.
Hope that, this will help you. Cheers !!!

How to encrypt the challenge phrase and answer for OpenAM Lost Password Management?

I recently had to convert challenge questions and passwords for an OpenAM implementation.
The plan was to convert these values as part of the user entry in a LDIF file and load it. The attribute to complete is iplanet-am-user-password-reset-question-answer. This is a multi valued attribute to support multiple question/answer pairs.
The challenge question key, answer and question key and question status flag had to be combined in a single line delimited by tabs.
[question-key]\t[answer]\t[1|0]
The value needs to be encrypted. This was the class used to encrypt but it did not work.
AMPasswordUtil().encrypt(question.get(challenge) + "\t" + response + "\t1")
What to do to make this work?
Finally gave up and dropped ForgeRock support a question. They were very helpful and supplied the solution and it worked immediately. Here it is...
It turns out the AMPasswordUtil class should not be used. Instead this should be used
encrypted_str = AccessController.doPrivileged(new EncodeAction( clear_text_str ))
The encryption key needs to be set as a system property
System.setProperty("am.encryption.pwd", key );
The encryption key can be retrieved from OpenAM.

Safely storing encrypted sensitive data 'publicly' online?

How can I safely store sensitive data online?
I want to store some extremely sensitive information online in a public folder, and I'm not sure how to go about it.
Specifically, I want to store bitcoin private keys in a .json file named "walletData.json" in a public folder. The file contains the wallet address and public key in plain text, along with an encrypted version of the private key.
Assuming anyone can access the file and attempt to crack the encryption password with their "super computers", what's the best way to safely encrypt that private key?
I know a longer password would be a good start, but ideally I don't want to need a password longer than 10 characters.
I was thinking of maybe hashing the password 1000 times, then using that hash+password as an AES encryption key. But, as everyone can see the key generation method, i'm not sure that will help? I was also thinking of padding out the encrypted private key with some other random data, but again, I don't know if it'll really help??
Is there a safe way to do this?
EDIT - after Reid's answer:
I'm trying to do this 100% in Javascript/jQuery.
When I export a CoinPrism.com wallet, I get this:
{"keys":[{"addr":"1PNLiLgW2fBokCB2wmfhZTtbmioitkqtMm","priv":"172655af193edeb54467a52fc6eb94c67eeeff8cd03555767e5cf12df694bb88f9c8b25c4019147d9e4993405274c96a","encryptionMode":"PKBDF2-SHA256","iterations":2000}],"salt":"2222b67fc7255aaf0b4027bfcabffb5e62f39e9e0aa13e8ad70f2dc75a484f26"}
The "priv" value is an encrypted private key. I don't know exactly how it's encrypted, but i'm sure that there's a way to decrypt it using just my 10 character password.
Does anyone know how they're doing this?
Is it safe to store this information online?
Well, I will just say outright that you don't need to be the one who writes the code to do this — it is far too easy to mess up, and your post makes suggestions that are concerning. (For instance, you describe something of an ad-hoc key derivation scheme, but one that is insufficient in protection.)
So, you need a library of some kind to handle this business for you.
My suggestion: Use GPG with the ASCII armor option. For example:
gpg --symmetric --armor --cipher-algo AES file.txt
This will symmetrically encrypt (--symmetric) a file (file.txt here) using the AES cipher (--cipher-algo AES) and store the resulting encrypted file in an ASCII armored format (--armor). Note: the resulting encrypted file will be stored in the filename plus the extension .asc; e.g., here, it puts the result in file.txt.asc. You can change this with the --output option.
Now, the above command will prompt you for a passphrase — this passphrase needs to be very strong, far more than 10 characters I'm afraid. This is the burden of passphrase-based encryption: you need passphrases that are strong. Ideally, you want a passphrase that is long and complicated, hard-to-guess and hard-to-bruteforce.
Since we are on StackOverflow, you may be looking to automate the passphrase entry (using scripting). To do that, there are several --passphrase related options for GPG. For example,
gpg --batch --passphrase "test" --symmetric --armor --cipher-algo AES file.txt
will use the passphrase test instead of prompting the user. Command line arguments are not safe, however, on a system, so it would be better to use the --passphrase-from-file option, which takes a single file as an argument. The first line of that file is the passphrase to be used.

Resources