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
Related
I am extracting some data from a UNIVERSE system and want to encrypt it for transfer via email.
I am no UNIVERSE expert so am using bits and pieces we have found from around the internet and it "looks" like it is working BUT I just can't seem to decrypt the data.
Below is the script I have used based on code found on the web:
RESULT=''
ALGORITHM="rc2-cbc" ; * 128 bit rc2 algorithm in CBC mode
MYKEY="23232323" ; * HEX - Actual Key
IV= "12121212" ; * HEX - Initialization Vector
DATALOC=1 ; * Data in String
KEYLOC=1 ; * Key in String
ACTION=5 ; * Base64 encode after encryption
KEYACTION=1 ; * KEY_ACTUAL_OPENSSL
SALT='' ; * SALT not used
RESULTLOC=1 ; * Result in String RESULT
OPSTRING = ''
RETURN.CODE=ENCRYPT(ALGORITHM,ACTION,DATASTRING,DATALOC,MYKEY,KEYLOC,KEYACTION,SALT,IV,OPSTRING,RESULTLOC)
RETURN.CODE = OPSTRING
Below are a few data strings I have processed through this script and the resulting string:
INPUT 05KI
OUTPUT iaYoHzxYlmM=
INPUT 05FOAA
OUTPUT e0XB/jyE9ZM=
When I try to decode and decrypt the resulting OUTPUT with an online decrypter, I still get no results: https://www.tools4noobs.com/online_tools/decrypt/
I'm thinking it might be a character encoding issue or perhaps the encryption is not working but I have no idea how to resolve - we have been working on this for a few weeks and cannot get any data that is decryptable...
All setups and fields have been set based on this: https://www.dropbox.com/s/ban1zntdy0q27z3/Encrypt%20Function.pdf?dl=0
If I feed the base-64 encrypted string from your code back into the Unidata DECRYPYT function with the same parameters it decrypts just fine.
I suspect something funny is happening with the key. This page mentions something like that: https://u2devzone.rocketsoftware.com/accelerate/articles/data-encryption/data-encryption.html "Generating a suitable key is one of the thornier problems associated with encryption. Keys should be generated as random binary strings, making them obviously difficult to remember. Accordingly, it is probably more common for applications to supply a pass phrase to the ENCRYPT function and have the function internally generate the actual encryption key."
One option to remove the Universe ENCRYPT function from the picture is to use openSSL directly. It looks like the ENCRYPT/DECRYPT functions are just thin wrappers around the openSSL library, so you can execute that to get the result. I'm having problems with the php page you're using for verification, but if I feed the base-64 encrypted string to an openSSL decrypt command on a different machine, it decrypts fine.
MYKEY="A long secret key"
DATASTRING="data to be encrypted data here"
EXECUTE '!echo "':DATASTRING:'"| openssl enc -base64 -e -rc2-cbc -nosalt -k "':MYKEY:'"' CAPTURING RESULT
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 have a client/server architecture in which I use the openssl library to implement an encrypted communication (TLSv1.2).
Since I'm using "self signed" certificates, in order to verify server's identity, my idea is to put in the client side a physical copy of the server's public key (server_public_key.pem) and then verify if it is equals to which received in the handshake phase of TLS.
On the client, I can retrieve the latter with:
X509 *cert = SSL_get_peer_certificate(ssl);
Now, I would extract the human readable string of the public key contained in this object.
I know that I can print it in this way:
EVP_PKEY *pkey = X509_get_pubkey(cert);
PEM_write_PUBKEY(stdout, pkey);
But I need to keep it as a string (instead of send it to stdout). How can I do this ?
Use BIO_new() to create a new BIO backed by an internal memory buffer (initially empty).
Then use PEM_write_bio_PUBKEY() to write the public key to the BIO, at which point use the functions documented in the BIO's manual page to retrieve the public key.
See the cited documentation for a simple example of creating a BIO, writing to it, then reading from it. Replacing the sample write operation with PEM_write_bio_PUBKEY() should be sufficient.
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.
So I am using the Crypto++ Library to encrypt a file. I need to save the key and iv for future use. I am following this tutorial. Here is my function :
void AESUtil::encrypt(string filename,bool savekeys,string savefilename){
AutoSeededRandomPool rnd;
// Generate a random key
byte key[AES::DEFAULT_KEYLENGTH];
rnd.GenerateBlock(key, AES::DEFAULT_KEYLENGTH);
// Generate a random IV
byte iv[AES::BLOCKSIZE];
rnd.GenerateBlock(iv, AES::BLOCKSIZE);
Binary b;
string plaintext = b.decoder(filename);
unsigned char *ciphertext= new unsigned char[plaintext.size()+1];
ciphertext[plaintext.size()]='\0';
if(savekeys){
ofstream("key.bin", ios::binary).write((char*)key, sizeof(key));
}
CFB_Mode<AES>::Encryption cfbEncryption(key, AES::DEFAULT_KEYLENGTH, iv);
cfbEncryption.ProcessData(ciphertext,reinterpret_cast<const unsigned char*>(plaintext.c_str()),plaintext.size()+1);
ofstream outfile(savefilename.c_str());
outfile.write((char*)ciphertext,sizeof(ciphertext));
}
The files contain data in �/���� format. I want to know the best method to save the key and iv programmatically which are a byte array to a file and the ciphertext which is a unsigned char* to a separate file.
The key could be saved in a separate file. Normally the key is established between sender / receiver in advance, or it is encrypted using a public key of the receiver. Note that it doesn't make sense to save the key next to the ciphertext, as it would provide no protection whatsoever. The handling of keys is called key management and entire books have been written about it.
The IV is a different animal. The IV should be randomly generated. For CFB it should at least be unique and identical at both sides. Usually the IV is simply prefixed to the ciphertext, it doesn't have to be kept secret.
Your key and iv variables are the key and IV used to encrypt the plain text.
You didn't fill either; you're actually using an array filled with 0 bytes as both the key and IV for your encryption.
The IV is public information. You don't need to hide it. Save it the way you want.
The KEY is what you must keep safe. To do that you may decide how much effort you want to put on it to hide it from the external factors.
I have some keys that I don't care to leave them as a "plain text" in the binary code. (NO SECURITY, but my mom can't figure out what to do, but a beginner in reverse engineer will laugh at it.)
Some keys I do a play with the bytes, like inverting parts, separating them, XOR with something. (Very unsafe, but better than nothing, a programmer with decent knowledge in reverse engineering will be able to spend some time and eventually break the security)
Some other cases I use 3rd party advanced obfuscation... If possible, depending on what you want, you may even replace your encryption engine with some "white-box" cryptography. Then you will have your keys very well protected. But this is usually hard/expensive. It doesn't seem to be your case. (Yes, even a very advanced assembly guru will not be happy to start reverse engineer this case.)
Another solution, if you don't need the key on your binary, is to give it to the system's password manager. On Windows, it's called "Data Protection API", and on Mac, it's called "Keychain". Take a look at these, and then you will understand why this is considered security. But it's because all the passwords here are encrypted with the "user password" so nothing is stored "on disk". A turned-off device in this scenario is considered very secure.