I am quite new to using PKCS#11 library so maybe someone with more experience can clear things up.
I want to do the following:
upload to HSM existing RSA public key (which was generated on PC)
and later use this uploaded key to wrap symmetric key that was generated on HSM.
I know how to generate symmetric key, but how to upload existing RSA public key?
Is this even possible using PKCS#11 library?
There seems to be similar question at Wrap a secret key with a public key using PKCS#11 but it uses RSA key pair that is generated on HSM. I need to upload RSA public key to HSM myself.
We can use C_CreateObject function of PKCS#11 to import a public key to HSM.
This can be found from
RSA PKCS#11
Functions -> Object Management Functions -> C_CreateObject
There is also an example of load public key. But it requires the support of token to load the public key from cryptoki library.
CK_SESSION_HANDLE hSession;
CK_OBJECT_HANDLE hKey;
CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
CK_KEY_TYPE keyType = CKK_RSA;
CK_BYTE modulus[] = {... };
CK_BYTE exponent[] = {... };
CK_ATTRIBUTE keyTemplate[] = {
{CKA_CLASS, &keyClass, sizeof(keyClass)}
,
{CKA_KEY_TYPE, &keyType, sizeof(keyType)}
,
{CKA_WRAP, &true, sizeof(true)}
,
{CKA_MODULUS, modulus, sizeof(modulus)}
,
{CKA_PUBLIC_EXPONENT, exponent, sizeof(exponent)}
};
CK_RV rv;
/* Create an RSA public key object */
rv = C_CreateObject(hSession, &keyTemplate, 5, &hKey);
if (rv == CKR_OK) {
.
.
}
Related
I have a requirement where I need to do Encryption of my Private Key using Public Key(provided by third party) with RSA/ECB/PKCS1 Encryption
The Public Key is already Padded.
I am generating the private key using cl_sec_sxml_writer=>generate_key( cl_sec_sxml_writer=>co_aes256_algorithm_pem ). Is this the correct way to generate a new key or we can have any random string as a private key?
This private key will be used to encrypt a data string using AES/ECB/PKCS7 padding encryption and then convert to BASE64 and send it via API call. For AES/ECB/PKCS7 padding, I am using the classes provided by following https://github.com/Sumu-Ning/AES. pfb implementation below:
CALL METHOD zcl_aes_utility=>encrypt_xstring
EXPORTING
i_key = lv_xstr
i_data = lv_pwd_xstr
* i_initialization_vector =
i_padding_standard = zcl_byte_padding_utility=>MC_PADDING_STANDARD_PKCS_7
i_encryption_mode = zcl_aes_utility=>mc_encryption_mode_ecb
IMPORTING
e_data = lv_encrypt
My query is , how do I encrypt the private key using public key and RSA/ECB/PKCS1 Encryption.
The public key is of length 399 chars and something like this
DfP4hVgyXMSNWJFWakwo44p1PMyRKSmFG+UGq
I have checked other blogs that asks to use standard fm SSF_KRN_ENVELOPE but I am not able to understand how to use it.
Please help. Let me know in case of any further details required.
When I create a public/private key using the following code :
// Create the CspParameters object and set the key container
// name used to store the RSA key pair.
CspParameters cp = new CspParameters();
cp.KeyContainerName = ContainerName;
// Create a new instance of RSACryptoServiceProvider that accesses
// the key container MyKeyContainerName.
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cp);
If I then call
rsa.Encrypt (....
OR
rsa.Decrypt(..
how do I know which key is being used. Whether the public or private key is used in each case is dependent on the application. How can I determine which is being used ?
Encrypt is done with the public key, and decrypt is done with the private key .. thus only the holder of the private key can decrypt.
You are not meant to decrypt using a public key, and thus the interface don't provide you with a way to do this.
Signatures utilizes encrypting using the private key, and decryption using the public key + some one way hash logic, but in this case the interface only allows this using specific signature methods (SignData(..) & VerifyData(..)).
Is it normal that the keypair of RSA (private and public) have the same ciphertext when I encrypt them with AES 256?
In fact I'm using PHP:
<?php
$key="abc";
$config = array(
"digest_alg" => "sha512",
"private_key_bits" => 4096,
"private_key_type" => OPENSSL_KEYTYPE_RSA,
);
// Create the private and public key
$res = openssl_pkey_new($config);
// Extract the private key from $res to $privKey
openssl_pkey_export($res, $privKey);
// Extract the public key from $res to $pubKey
$pubKey = openssl_pkey_get_details($res);
$pubKey= $pubKey["key"];
aes256Key = hash("SHA256", $password, true);
// for good entropy (for MCRYPT_RAND)
srand((double) microtime() * 1000000);
// generate random iv
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_RAND);
$crypted_priv= rtrim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $privKey, MCRYPT_MODE_CBC, $iv)), "\0\3");
$crypted_pub= rtrim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $pubKey, MCRYPT_MODE_CBC, $iv)), "\0\3");
?>
UPDATE: I replaced ECB with CBC and hope its correct...
You are not getting the public key with openssl_pkey_get_details(). That structure contains both the public exponent e and private exponent d. It is normal that the private key also contains the public exponent. Most of the time that is a static value (such as 65537, the fourth number of Fermat).
According to the documentation of openssl_pkey_new you can get to the public key using the method openssl_pkey_new():
openssl_pkey_new() generates a new private and public key pair. The public component of the key can be obtained using openssl_pkey_get_public().
That's not the only thing that goes wrong though:
You are not using AES. Rijndael with a block size of 256 is not AES. AES has a block size of 128 bits.
Although mcrypt always expects an IV, ECB mode does not - but read on.
ECB mode is not secure for anything other than random data, you should be using CBC mode to encrypt asymmetric keys (as they almost always contain a structure that may leak information); CBC mode does require a random IV.
You are using the ASCII representation of a string instead of an AES key; you should use a Password Based Key Derivation function such as PBKDF2, bcrypt or scrypt instead. PHP mcrypt is far too forgiving regarding insecure keys.
Note that in general I would also advise a padding mode such as PKCS#7. Mcrypt however does not implement any sane padding method, so you would have to implement that yourself.
There are already formats for storing private keys encrypted. eg.
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,E3B1C06E0D0C2633
gvmXzl6W7eV1a3N5rQNwBWKY9on3IgxZudS33cip5f88FotsPSDJMvqj6LVw2RxobDjhlOOzqmTb
VrlTnoQ6CogXFZSfiPmixiyyptCUEKJkSiEhYGM5GQm0OoGcLeLbgBb9tRpWh5IlXulKD6XFhx8q
/eGg5a+mSkX1i7kv2+Ih3jHmEKwrnfzhcA29pBF3OQJo+Ks9IYneuk676pHtsIs7CpFKq1tDvD8Q
O7URxnVnHLltaFvIxshqyZu92xbUYZR7YzjXl5+3w4TVgeAHUogEV+H9iZTosD/copUsbQO+78w2
E1D3iDS94wRgx0Tjv4xlwrTpOV38FS5rdL32492DcCRlCYM4VtuwjYeWi5shJg69jCb0EwGRqfAo
xko+lbKWELTuFKwD7n1rc/2fTarbGuf8S2AEggBLZyfXHC/9N84mXLFO2XKq+0WdiEFhQj2Cze+a
9qcSK6tPSrjK1LPlnOOppFgDElZaZ0rxsgjtiWSIAEw/Ad+SIM5u+vqwzF8J317JlsdKoBFDw8mS
MxCMuMksKJ23mgvY+THRIVgH3E7lEDZQzCi1Uy6ldLJcran/6wHwP88pVM2odiHkpnrJGcEBbbIk
qsxJZhFT8aUt/cUEBj3fnP7cxoNLQfTHMPqUTqKBWaVufFzGU9YB1R+XWFULLddwJHnV7gPheBlk
MDapowb+Is77+a9Y2VDsOXEvNpqTY0giiSrckG05IZnrhJ24JnSCwyNd99lm7XKdEGGrjBCMqIyI
Fqox8Ahkv3KWAJPYK1eOCc5d/KwZHlnlFJq7ZYy9u3fEnxQCjOEmeXLkLangKA==
-----END RSA PRIVATE KEY-----
...or stronger yet...
PuTTY-User-Key-File-2: ssh-rsa
Encryption: aes256-cbc
Comment: phpseclib-generated-key
Public-Lines: 3
AAAAB3NzaC1yc2EAAAADAQABAAAAgQCqGKukO1De7zhZj6+H0qtjTkVxwTCpvKe4
eCZ0FPqri0cb2JZfXJ/DgYSF6vUpwmJG8wVQZKjeGcjDOL5UlsuusFncCzWBQ7RK
NUSesmQRMSGkVb1/3j+skZ6UtW+5u09lHNsj6tQ51s1SPrCBkedbNf0Tp0GbMJDy
R4e9T04ZZw==
Private-Lines: 7
llx04QMegql0/nE5RvcJSrGrodxt6ytuv/JX2caeZBUyQwQc2WBNYagLHyHPM9jI
9OUWz59FLhjFXZMDNMoUXxVmjwQpOAaVPYNxxFM9AF6/NXFji64K7huD9n4A+kLn
sHwMLWPR5a/tZA0r05DZNz9ULA3mQu7Hz4EQ8ifu3uTPJuTmL51x6RmudYKysb20
fM8VzC3ukvzzRh0pujUVTr/yQdmciASVFnZlt4xQy+ZEOVUAOfwjd//AFfXTvk6x
7A45rNlU/uicHwLgoY1APvRHCFxw7F+uVW5L4mSX7NNzqBKkZ+1qpQTAfQvIfEIb
444+CXsgIyOpqt6VxJH2u6elAtE1wau3YaFR8Alm8m97rFYzRi3oDP5NZYkTCWSV
EOpSeghXSs7IilJu8I6/sB1w5dakdeBSFkIynrlFXkO0uUw+QJJWjxY8SypzgIuP
DzduF6XsQrCyo6dnIpGQCQ==
Private-MAC: 35134b7434bf828b21404099861d455e660e8740
You should stick with an already standardized format rather than trying to make your own up.
And why are you encrypting the public key? As the name implies the public key is kinda supposed to be public ;)
I need to do a GET/PUT/DELETE/POST message on httpwebrequest.
my request body contains XML.
I need to encrypt the content in body XML and decrypt back on the client/receiver side.
I see there are multiple ways to encrypt the XML.
one of it is here http://msdn.microsoft.com/en-us/library/sb7w85t6.aspx
But my concern is, receiver should be able to decrypt it. and receiver shoul dbe on different platform might not be on .NET framework.
Can any one suggest a best approach for this.
What i have tried so far:
// Create a new Rijndael key.
key = new RijndaelManaged();
// Load an XML document.
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.PreserveWhitespace = true;
xmlDoc.Load("test.xml");
// Encrypt the "creditcard" element.
Encrypt(xmlDoc, "creditcard", key);
Console.WriteLine("The element was encrypted");
Console.WriteLine(xmlDoc.InnerXml);
Decrypt(xmlDoc, key);
Console.WriteLine("The element was decrypted");
Console.WriteLine(xmlDoc.InnerXml);
This looks to be doing the job. But I have concerns about the key
key = new RijndaelManaged();
Decrypt(xmlDoc, key);
What is this Key, will client on different machine and different framework and different technology be able to decrypt this message?
Update
After my research on few encryption methods, I found X509Certificate2 is best encryption option and client can also able to decrypt it, if the same X509 cert is installed on their machine.
I could find a script to encrypt
public static void Encrypt(XmlDocument Doc, string ElementToEncrypt, X509Certificate2 Cert)
{
// Check the arguments.
if (Doc == null)
throw new ArgumentNullException("Doc");
if (ElementToEncrypt == null)
throw new ArgumentNullException("ElementToEncrypt");
if (Cert == null)
throw new ArgumentNullException("Cert");
XmlElement elementToEncrypt = Doc.GetElementsByTagName(ElementToEncrypt)[0] as XmlElement;
// Throw an XmlException if the element was not found.
if (elementToEncrypt == null)
{
throw new XmlException("The specified element was not found");
}
EncryptedXml eXml = new EncryptedXml();
// Encrypt the element.
EncryptedData edElement = eXml.Encrypt(elementToEncrypt, Cert);
EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);
}
If found this code to decrypt
public static void Decrypt(XmlDocument Doc)
{
// Check the arguments.
if (Doc == null)
throw new ArgumentNullException("Doc");
// Create a new EncryptedXml object.
EncryptedXml exml = new EncryptedXml(Doc);
// Decrypt the XML document.
exml.DecryptDocument();
}
My question is this decrypt method is not asking for and X509 key. So how is it decrypting, doesn't it need and key to decrypt. Will this decryption works on other machines as well.
There exist several approaches to encryption.
Symmetric encryption uses the same key to encrypt and decrypt the data. AES encryption algorithm is an example of such encryption.
Asymmetric (public- and private-key based) encryption uses a pair of keys. In this mode you encrypt the data for someone using his public key. He uses his private key (which you don't have and should not have) to decrypt the data prepared for him. Asymmetric encryption is accomplished using certificate-based PKCS#7 / CMS standard or using OpenPGP.
Now about XML. You can encrypt it as if it were binary data using one of the above methods. Or you can encrypt it using XMLEnc standard.
The way to use depends on who decides or demands encryption format and method. If it's you that makes the decision, then the decision should be based on what capabilities (libraries, code) both sides can use AND how the keys are managed (PKI is a bit harder to manage than symmetric key, but in general PKI is more secure).
Just a note: our SecureBlackbox product supports both symmetric and certificate-based encryption (both binary, XMLEnc and also OpenPGP) on .NET, Java and other platforms.
I am trying to wrap a generated symmetric key using the public key which i want to extract it from the Public Certificate(.der / .cer ) when i am passing the public key for wrapping the symmetric key i am getting an "java.security.InvalidKeyException" exception "Only keys that exist in 'RAW' format are supported"
When i am loading the public certificate using file input stream as
publicCertificate = new X509Certificate(new FileInputStream("src/resources/mydomain.com.der"));
for extracting the publicKey i am using this getPublicKey(); method
publicKey = publicCertificate.getPublicKey();
I am such exception when i extracted the public key and it is in the X.509 format which i need to convert it into RAW format.
Can anyone please help me out here.
Thanks in Advance.