I need to generate SHA256 of some data. I found this example is a very good one. Now my question is Can I generate a sha256 by using my own key.
EDIT:
First of all, sorry for wrong question. I don't mean that to change the key used to generate SHA256. I really need is that, to convert the following java code to c++
public static String calculateHMAC(String data, String key) throws Exception {
String result;
try {
// get an hmac_sha2 key from the raw key bytes
SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), HMAC_SHA2_ALGORITHM);
// get an hmac_sha1 Mac instance and initialize with the signing key
Mac sha256_HMAC = Mac.getInstance(HMAC_SHA2_ALGORITHM);
sha256_HMAC.init(signingKey);
// compute the hmac on input data bytes
byte[] rawHmac = sha256_HMAC.doFinal(data.getBytes());
// base64-encode the hmac
StringBuilder sb = new StringBuilder();
char[] charArray = Base64.encode(rawHmac);
for ( char a : charArray){
sb.append(a);
}
result = sb.toString();
}
catch (Exception e) {
throw new SignatureException("Failed to generate HMAC : " + e.getMessage());
}
return result;
}
Edit (as OP changed the question):
There are lots of C++ libraries available for cryptographic operations:
OpenSSL (My personal choice, we use this library in our industry products).
Crypto++.
Here's an example of Generate sha256 with OpenSSL and C++.
OLD ANSWER:
SHA-256 is a member of SHA-2 cryptographic hash functions family, which usually generates 256 bits or 32 bytes HASH code from an input message.
It's not an "encryption" mechanism which means, from the HASH (also known as message digest or digest) you can not regenerate the message.
Therefore, we do not need any "keys" to generate SHA-256 message digest.
Moreover, hash functions are considered practically impossible to invert, that is, to recreate the input data from its hash value (message digest) alone. So You can't "decrypt" a HASH message/message digest to its input message, which concludes reversing is not possible for Hashing. For example,
SHA256(plainText) -> digest
Then there is NO mechanism like inverseSHA256 which can do the following,
// we cannot do the following
inverseSHA256(digest) -> plainText
I would recommend the free Crypto++ library. Here's a sample for HMAC.
Related
I am developing rest api system running on ec2 service.
My requirement is
encrypt/decrypt on plain text with AES256
generate key with pbkdf2
Store key on aws cloud system
Java
I tried to used KMS & Crypto sdk but it’s not working. (ex) result of encryption value is changed every time When I called method with same plaint text.
Do you have any ideas?
public String encrypt(String text) {
String plaintext = text;
try {
ByteBuffer byteBuffer = getByteBuffer(plaintext);
EncryptRequest encryptRequest = new EncryptRequest().withKeyId(key_arn).withPlaintext(byteBuffer);
EncryptResult encryptResult = client.encrypt(encryptRequest);
String ciphertext = getString(java.util.Base64.getEncoder().encode(encryptResult.getCiphertextBlob()));
plaintext = ciphertext;
} catch (Exception e) {
e.printStackTrace();
}
return plaintext;
}
public String decrypt(String text) {
String bb = null;
try {
byte[] ciphertextBytes = text.getBytes();
DecryptRequest request = new DecryptRequest();
request.setCiphertextBlob(ByteBuffer.wrap(ciphertextBytes));
DecryptResult result = client.decrypt(request);
// Convert to byte array
byte[] plaintext = new byte[result.getPlaintext().remaining()];
ByteBuffer a = result.getPlaintext().get(plaintext);
bb = getString(a);
} catch (Exception e) {
e.printStackTrace();
}
return bb;
}
This is a hard question to answer succinctly because there are a lot of details and background knowledge that go into crypto and using the AWS crypto capabilities correctly.
First to your specific question - different values from the same plaintext is ok and expected. Encrypt returns different values for the same plain text because it attaches additional data to the plain text, such as an Initialization Vector (IV). This is a way to include non-deterministic data in the plain text precisely so that you don't end up with the exact same cipher text from the same plain text when using the same key.
More importantly, though, note that Encrypt and Decrypt are not general-purpose tools - they are designed to handle small payloads (< 8KB), specifically Data Keys. So where you go from here will depend on what kind of data you are encrypting. If you just need to decrypt a small value like a password, you can continue with Encrypt/Decrypt, and don't worry that two Encrypt operations produce different cipher texts. If you need to encrypt files or other arbitrary chunks of data, read on.
AWS promotes the idea of Envelope Encryption, which is the notion that the key used to actually en/decrypt is stored alongside data it protects, and is itself en/decrypted via a separate master key. In the AWS case, that's Customer Master Key (CMK), which never leaves KMS.
So you can use Encrypt to encrypt an encryption key that you generate, or you could use the AWS method GenerateDataKey to 1) create a key and 2) encrypt it for you. That will return both a plaintext (base64) and cipher text version of the key. Use the plaintext in memory, store the cipher text to disk.
A more typical workflow would be something like:
Call GenerateDataKey - you need to specify the KeyId and a KeySpec (AES_128 or AES_256). There are also options to generate asymmetric keys.
The result includes both a plain text and encrypted version of the generated key. Store the encrypted version.
At some later time, call Decrypt when you need to use the key.
Use the plaintext from that Decrypt method as the key in your local crypto code.
AWS actually provides a separate library to do all that for you - the AWS Encryption SDK, with support for a range of languages including Java. I've not used it extensively, but it provides the framework to do envelope encryption via best practices (which algorithms, master vs. data keys, etc). Take a look (link below).
Hope this helps; encryption is tough to get right.
For more info:
https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#enveloping
https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/introduction.html
https://en.wikipedia.org/wiki/Initialization_vector
I am trying to RSA public key decrypt a signed file using wolfcrypt - yes, I may or may not be abusing the "sign/verify" power of RSA to encrypt a separate AES key using the private key and decrypt using the public key.
Unfortunately, I am stuck at wc_RsaSSL_Verify() - for the life of me I can't figure out why it is returning BAD_FUNC_ARG - I figured an error like that should be immediately visible to somebody else so I'm deciding to call upon the collective powers of StackOverflow.
As far as I can tell, I'm giving the function what it's asking for - an input buffer, an output buffer, the size of each, and a pointer to the RsaKey struct. Here is a code snippet from the function in question:
bool VerifyWorker::GetAESKey()
{
bool result = true;
uint8_t en_aes_file_buff[VerifyWorkerLocal::RSA_KEY_SIZE];
uint8_t de_aes_file_buff[VerifyWorkerLocal::RSA_KEY_SIZE];
uint8_t* aes_iv_ptr = NULL;
// keyfile filestream
std::fstream aes_file;
// rsa_key must be initialized
if(rsa_key == NULL)
{
result = false;
}
// Open the key file and read it into a local buffer, then decrypt it and use it to initialize the
// aes struct
if(result)
{
aes_file.open(this->aes_key_file, std::ios_base::in | std::ios_base::binary);
if(aes_file.fail())
{
// Unable to open file - perror?
perror("GetAESKey");
result = false;
}
else
{
aes_file.read(reinterpret_cast<char*>(en_aes_file_buff), VerifyWorkerLocal::RSA_KEY_SIZE + 1);
if(!aes_file.eof())
{
// we didn't have enough space to read the whole signature!
std::cerr << "aes_file read failed! " << aes_file.rdstate() << std::endl;
result = false;
}
}
}
// "Unsign" the aes key file with RSA verify, and load the aes struct with the result
if(result)
{
int wc_ret = 0;
wc_ret = wc_RsaSSL_Verify(const_cast<const byte*>(en_aes_file_buff),
VerifyWorkerLocal::RSA_KEY_SIZE, reinterpret_cast<byte*>(&de_aes_file_buff),
VerifyWorkerLocal::RSA_KEY_SIZE, rsa_key);
The rsa_key is a private member initialized (successfully, using wc_PublicKeyDecode()) in a separate function with a public key DER file. I generated both the public and private key using OpenSSL - which should properly pad my AES key and iv file using PKCS#1 v1.5 b default.
I should also mention that I am using wolfssl version 3.9.8. Thanks!
The issue, I found, was that the file that I had signed with my RSA key was not signed correctly. When I signed the file using OpenSSL, my cli invocation was
openssl rsautl -in keyfile -out keyfile -inkey private.pem -sign
Apparently, openssl does not like you to specify the same file for -in and -out. When I changed it to something like
openssl rsautl -in keyfile -out keyfile_signed -inkey private.pem -sign
I was actually able to verify the file using wc_RsaSSL_Verify.
So, like most stupid late-night, last hour software problems, I was looking in the wrong place entirely. I was a bit thrown off by the BAD_FUNC_ARG being returned and thought that it had to do explicitly with the format of the function arguments, not necessarily their content. Hopefully this answer is useful for somebody else, too.
It sounds like you are trying to use RSA_Sign to perform an "Encrypt" of an AES key. Then I assume you are sending to a remote partner or computer who will then run an RSA_Verify operation to decrypt the AES key do I understand the scenario correctly?
If so I apologize it did not show up if you searched on how to do this initially but we actually have an example of doing exactly that here:
https://github.com/wolfSSL/wolfssl-examples/tree/master/signature/encryption-through-signing
That example includes two separate applications. The first app, "rsa-private-encrypt-app.c", will sign (encrypt) the "fake Aes Key" and output the result to a file. The second app, "rsa-public-decrypt-app.c", then opens the file that was output and does a verify (decrypt) on the data contained in the file to recover the original "fake Aes Key".
I may or may not be abusing the "sign/verify" power of RSA to encrypt a separate AES key using the private key and decrypt using the public key.
No not at all, that is a valid use of RSA sign/verify ASSUMING you are working with fixed-length inputs such as an AES key.
That's why we created the example! We actually had a user ask a very similar question on our forums awhile back which led to us making the example.
One thing to make note of though on the issues you encountered with openssl and wolfssl is actually talked about in the README:
https://github.com/wolfSSL/wolfssl-examples/blob/master/signature/encryption-through-signing/README.md
... Keep in mind this is not a TRUE RSA ENCRYPT and will likely not inter-op with other libraries that offer a RSA_PRIVATE_ENCRYPT type API.
This is a true SIGN operation.
If you have any other questions feel free to post them here (and add the wolfssl tag of course) or you can also send us an email anytime at support#wolfssl.com
Disclaimer: I work for wolfSSL Inc.
I am struggling with the OpenSSL API for C++ at the moment. I'm using the EVP functions to generate a RSA keypair which then is used to encrypt the AES key that was used for encrypting the data (hybrid encryption).
Key generation:
EVP_PKEY* keypair = NULL;
EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
EVP_PKEY_keygen_init(ctx);
EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 4096);
EVP_PKEY_keygen(ctx, &keypair);
EVP_PKEY_CTX_free(ctx);
Now I have a keypair. When Encrypting a message on my own machine via EVP_SealInit / EVP_SealUpdate / EVP_SealFinal there is no problem. Same for the decrypting process. I simply give keypair as an argument to the SealInit / OpenInit function.
But consider that I want to generate a keypair and send the public or private key as a char* over a socket to another person: how do I do that?
One way I found in the Internet is using PEM_write_bio_PUBKEY or PEM_write_bio_PrivateKey to convert the Keys to char*. When trying it seemed to work. But I'm still not 100% sure. So Please look at my code and tell me if those functions are the way to go:
unsigned char* publicKey;
BIO* bio = BIO_new(BIO_s_mem());
PEM_write_bio_PUBKEY(bio, keypair);
RSAmakeString(&publicKey, bio);
unsigned char* privateKey;
BIO* bio = BIO_new(BIO_s_mem());
PEM_write_bio_PrivateKey(bio, keypair, NULL, NULL, 0, 0, NULL);
RSAmakeString(&privateKey, bio);
The other thing is how do I convert the char* back to EVP_PKEY*? Are there any functions? Because if I want to use SealInit with my public Key on another computer I have to convert it back from a char* to an EVP_PKEY*, so I can use it in the function. Any suggestions?
But consider that I want to generate a keypair and send the public or private key as a char* over a socket to another person: how do I do that?
You need something for serialization and wire formats or a presentation format. Your public key and encrypted messages will likely have 0 characters, which appear as embedded NULL. So you need to have both a buffer and explicit length .
Use Google's ProtocolBuffers, Binary JSON, or even ASN.1/DER encoding. I think Google's ProtocolBuffers are message oriented, so they won't return a message until the complete message is available.
You could also Hex, Base32 or Base64 encode it. But you still need to communicate a length so the receiving party knows they got the whole message. On a local LAN you will probably never experience a problem. Over the Internet you will probably get occasional failures as your perform short reads on occasion.
Your thoughts on PEM_write_bio_PUBKEY are effectively Base64 encoding the key, so it suffers the same potential problem as Hex, Base32 or Base64 encoding.
how do I convert the char* back to EVP_PKEY
Well, you probably won't be using a char* based on your changes above. Once you refine the design, you should probably ask a new question.
But at the moment, and given you saved the key with PEM_write_bio_PUBKEY and PEM_write_bio_PrivateKey, then you would use PEM_read_bio_PUBKEY or PEM_read_bio_PrivateKey, respectively. Also see OpenSSL's PEM man page.
Related to C++, here are some tricks when working with OpenSSL. If you are using C++11, then unique_ptr really makes it easy to work with some OpenSSL objects.
unique_ptr and OpenSSL's STACK_OF(X509)*
How to get PKCS7_sign result into a char * or std::string
Non-printable character after generating random n-byte Base64 string
EVP Symmetric Encryption and Decryption | C++ Programs on the OpenSSL wiki
I've generated a random 256 bit symmetric key, in a file, to use for encrypting some data using the OpenSSL command line which I need to decrypt later programmatically using the OpenSSL library. I'm not having success, and I think the problem might be in the initialization vector I'm using (or not using).
I encrypt the data using this command:
/usr/bin/openssl enc -aes-256-cbc -salt -in input_filename -out output_filename -pass file:keyfile
I'm using the following call to initialize the decrypting of the data:
EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, keyfile.data(), nullptr))
keyfile is a vector<unsigned char> that holds the 32 bytes of the key. My question is regarding that last parameter. It's supposed to be an initialization vector to the cipher algorithm. I didn't specify an IV when encrypting, so some default must have been used.
Does passing nullptr for that parameter mean "use the default"? Is the default null, and nothing is added to the first cipher block?
I should mention that I'm able to decrypt from the command line without supplying an IV.
What is the default IV when encrypting with EVP_aes_256_cbc() [sic] cipher...
Does passing nullptr for that parameter mean "use the default"? Is the default null, and nothing is added to the first cipher block?
There is none. You have to supply it. For completeness, the IV should be non-predictable.
Non-Predictable is slightly different than both Unique and Random. For example, SSLv3 used to use the last block of ciphertext for the next block's IV. It was Unique, but it was neither Random nor Non-Predictable, and it made SSLv3 vulnerable to chosen plaintext attacks.
Other libraries do clever things like provide a null vector (a string of 0's). Their attackers thank them for it. Also see Why is using a Non-Random IV with CBC Mode a vulnerability? on Stack Overflow and Is AES in CBC mode secure if a known and/or fixed IV is used? on Crypto.SE.
/usr/bin/openssl enc -aes-256-cbc...
I should mention that I'm able to decrypt from the command line without supplying an IV.
OpenSSL uses an internal mashup/key derivation function which takes the password, and derives a key and iv. Its called EVP_BytesToKey, and you can read about it in the man pages. The man pages also say:
If the total key and IV length is less than the digest length and MD5 is used then the derivation algorithm is compatible with PKCS#5 v1.5 otherwise a non standard extension is used to derive the extra data.
There are plenty of examples of EVP_BytesToKey once you know what to look for. Openssl password to key is one in C. How to decrypt file in Java encrypted with openssl command using AES in one in Java.
EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, keyfile.data(), nullptr))
I didn't specify an IV when encrypting, so some default must have been used.
Check your return values. A call should have failed somewhere along the path. Maybe not at EVP_DecryptInit_ex, but surely before EVP_DecryptFinal.
If its not failing, then please file a bug report.
EVP_DecryptInit_ex is an interface to the AES decryption primitive. That is just one piece of what you need to decrypt the OpenSSL encryption format. The OpenSSL encryption format is not well documented, but you can work it backwards from the code and some of the docs. The key and IV computation is explained in the EVP_BytesToKey documentation:
The key and IV is derived by concatenating D_1, D_2, etc until enough
data is available for the key and IV. D_i is defined as:
D_i = HASH^count(D_(i-1) || data || salt)
where || denotes concatentaion, D_0 is empty, HASH is the digest
algorithm in use, HASH^1(data) is simply HASH(data), HASH^2(data) is
HASH(HASH(data)) and so on.
The initial bytes are used for the key and the subsequent bytes for the
IV.
"HASH" here is MD5. In practice, this means you compute hashes like this:
Hash0 = ''
Hash1 = MD5(Hash0 + Password + Salt)
Hash2 = MD5(Hash1 + Password + Salt)
Hash3 = MD5(Hash2 + Password + Salt)
...
Then you pull of the bytes you need for the key, and then pull the bytes you need for the IV. For AES-128 that means Hash1 is the key and Hash2 is the IV. For AES-256, the key is Hash1+Hash2 (concatenated, not added) and Hash3 is the IV.
You need to strip off the leading Salted___ header, then use the salt to compute the key and IV. Then you'll have the pieces to feed into EVP_DecryptInit_ex.
Since you're doing this in C++, though, you can probably just dig through the enc code and reuse it (after verifying its license is compatible with your use).
Note that the OpenSSL IV is randomly generated, since it's the output of a hashing process involving a random salt. The security of the first block doesn't depend on the IV being random per se; it just requires that a particular IV+Key pair never be repeated. The OpenSSL process ensures that as long as the random salt is never repeated.
It is possible that using MD5 this way entangles the key and IV in a way that leaks information, but I've never seen an analysis that claims that. If you have to use the OpenSSL format, I wouldn't have any hesitations over its IV generation. The big problems with the OpenSSL format is that it's fast to brute force (4 rounds of MD5 is not enough stretching) and it lacks any authentication.
I have following code in C#
PasswordDeriveBytes DerivedPassword = new PasswordDeriveBytes(Password, SaltValueBytes,
HashAlgorithm, PasswordIterations);
byte[] KeyBytes = DerivedPassword.GetBytes(32);
.Net's PasswordDeriveBytes uses PBKDF1. I am using "SHA1" hashing algorithm to generate 32 byte key.
Kindly tell me how I can achieve this in crypto++. In crypto++ using PBKDF2 its generate 20 byte key. How can I make 32 byte key which C# generating.
You can't, because PasswordDerivedBytes is not standard PBKDF1, while the crypto++ implementation is. Use the PBKDF2 implementation instead (Rfc2898DeriveBytes in .NET).