Use aws-encryption-sdk to decrypt with context in on-prem environment - python-3.x

I want to consume encrypted messages using the aws_encryption_sdk python module. The messages are encrypted by another team using a context.
The reason to use aws_encryption_sdk is to reduce the cost by reducing the number of KMS sessions whenever we call the boto3 kms client decrypt function. However, I seem to be stuck and confused as I can't find where I can use that when calling the decrypt function for the EncryptionSDKClient
My code looks something like this:
client = aws_encryption_sdk.EncryptionSDKClient()
## try to set the botocore session for Master Key Provider
kms_kwargs= dict(key_ids=data['keyId'])
key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider(**kms_kwargs)
MAX_ENTRY_AGE_SECONDS = 600.0
MAX_ENTRY_MESSAGES = 10
MAX_CACHE_SIZE = 10
cache = aws_encryption_sdk.LocalCryptoMaterialsCache(MAX_CACHE_SIZE)
caching_cmm = CachingCryptoMaterialsManager(
master_key_provider=key_provider,
cache=cache,
max_age=MAX_ENTRY_AGE_SECONDS,
max_messages_encrypted=MAX_ENTRY_MESSAGES
)
cycled_plaintext, decrypted_header = client.decrypt(source=base64.b64decode(data["encryptedData"]), key_provider=key_provider)
Please note that I need to cache the data key in on-premise environment.

From the AWS Developer Guide on KMS Encryption SDK page, encryption context section:
To decrypt the data, you pass in the encrypted message. Because the AWS Encryption SDK can extract the encryption context from the encrypted message header, you are not required to provide the encryption context separately. However, the encryption context can help you to confirm that you are decrypting the correct encrypted message.
There is also a few examples of code verifying the encryption contexts that you may find useful here.

Related

is installing local node necessary to create wallet on test/main net?

i want to be able to create wallets on wave blockchain using their api
according to this
https://nodes-testnet.wavesnodes.com/api-docs/index.html#/addresses/createWalletAddress
i need to send API key in my request header .... i look into how can i obtain this api key and in the doc here are the steps
Set API Key
To set API key, you need to generate API key hash and then use it in
your node configuration.
Create unique string value that you will use as API key.
Go to Swagger web interface.
Open the /utils/hash/secure (opens new window)API method and input
your unique string in the message field.
Click Execute to get the hashed API key.
Use the hashed API key as the value of the api-key-hash parameter in
your node configuration file.
Restart your node.
it says
Use the hashed API key as the value of the api-key-hash parameter in
your node configuration file.
im very confused ... i thought using testnet means that i dont have to install a local node
maybe im wrong ?!
use this package
https://www.npmjs.com/package/#waves/waves-api
you need to creaate a seed pharase , and using the seed you can create address/public & private keys ... here is a shortcut to create all
const Waves = WavesAPI.create(WavesAPI.TESTNET_CONFIG);
const seed = Waves.Seed.create();
console.log(seed);

Ignore Default AWS KMS Encryption for S3 Uploads Using Python Boto3

We recently enabled AWS KMS for all of our Amazon S3 buckets which, by default, applies server-side encryption to all files we upload to our own S3 buckets or to S3 buckets owned by someone else.
Is there a way to intentionally "ignore" the default KMS encryption to upload unencrypted files to an S3 bucket owned by a 3rd party? The 3rd party team cannot open any of the files we are sending them. I understand that one solution would be to share the KMS key with the 3rd party but, due to the nature of the relationship, it's better if we only deliver unencrypted files instead of sharing a key.
Here is the Python code I have been using to deliver the files. How can I modify the ExtraArgs parameter to intentionally ignore the default KMS encryption?
from boto3 import client
from boto3.s3.transfer import TransferConfig
client = client('s3', ...)
config = TransferConfig(multipart_threshold=1024 * 25, multipart_chunksize=1024 * 25,
max_concurrency=10, use_threads=True)
client.upload_file(filename='test.csv', bucket='my-bucket', key='test.csv',
Config=config, ExtraArgs={'ACL': 'bucket-owner-full-control'})

Require key file by path in Google Cloud Function

I have the functions for Google Cloud Function that needs to require json key file.
For example:
const SERVICE_ACCOUNT_EMAIL = 'your_service_account_email#developer.gserviceaccount.com';
const SERVICE_ACCOUNT_KEY_FILE = require('./path/to/your/service_account.json');
const jwtClient = new google.auth.JWT(
SERVICE_ACCOUNT_EMAIL,
null,
SERVICE_ACCOUNT_KEY_FILE.private_key,
['https://www.googleapis.com/auth/androidpublisher'],
null
);
How I can get access for SERVICE_ACCOUNT_KEY_FILE? Where should I upload the file and how next do I will find its path?
This is a key from the private/public key pair that you create. It will be wrapped inside a JSON (at least that is the common usage). See examples here and documentation here. Never share your private key, but you can freely share your public key (in fact it is required that you share your public key). And don't put your private key into a source control (git repo).
You can find a lot of good information about asymmetric asymmetric cryptography (public key cryptography) online.
In case you are wondering where to add the key file, it should be here: https://www.npmjs.com/package/google-oauth-jwt#creating-a-service-account-using-the-google-developers-console
UPDATE:
Where should you add the file to be able to access it:
One of the best practice is to put the file in a bucket, to allow the function service account (the default one or a specific identity) to read this bucket and to load the file at runtime. One of the main reason is that you don't have to commit your security file, you just have to keep a reference to a bucket.
Reference

How can I sign a JWT token on an Azure WebJob without getting a CryptographicException?

I have a WebJob that needs to create a JWT token to talk with an external service. The following code works when I run the WebJob on my local machine:
public static string SignES256(byte[] p8Certificate, object header, object payload)
{
var headerString = JsonConvert.SerializeObject(header);
var payloadString = JsonConvert.SerializeObject(payload);
CngKey key = CngKey.Import(p8Certificate, CngKeyBlobFormat.Pkcs8PrivateBlob);
using (ECDsaCng dsa = new ECDsaCng(key))
{
dsa.HashAlgorithm = CngAlgorithm.Sha256;
var unsignedJwtData = Base64UrlEncoder.Encode(Encoding.UTF8.GetBytes(headerString)) + "." + Base64UrlEncoder.Encode(Encoding.UTF8.GetBytes(payloadString));
var signature = dsa.SignData(Encoding.UTF8.GetBytes(unsignedJwtData));
return unsignedJwtData + "." + Base64UrlEncoder.Encode(signature);
}
}
However, when I deploy my WebJob to Azure, I get the following exception:
Microsoft.Azure.WebJobs.Host.FunctionInvocationException: Exception while executing function: NotificationFunctions.QueueOperation ---> System.Security.Cryptography.CryptographicException: The system cannot find the file specified. at System.Security.Cryptography.NCryptNative.ImportKey(SafeNCryptProviderHandle provider, Byte[] keyBlob, String format) at System.Security.Cryptography.CngKey.Import(Byte[] keyBlob, CngKeyBlobFormat format, CngProvider provider)
It says it can't find a specified file, but the parameters I am passing in are not looking at a file location, they are in memory. From what I have gathered, there may be some kind of cryptography setting I need to enable to be able to use the CngKey.Import method, but I can't find any settings in the Azure portal to configure related to this.
I have also tried using JwtSecurityTokenHandler, but it doesn't seem to handle the ES256 hashing algorithm I need to use (even though it is referenced in the JwtAlgorithms class as ECDSA_SHA256).
Any suggestions would be appreciated!
UPDATE
It appears that CngKey.Import may actually be trying to store the certificate somewhere that is not accessible on Azure. I don't need it stored, so if there is a better way to access the certificate in memory or convert it to a different kind of certificate that would be easier to use that would work.
UPDATE 2
This issue might be related to Azure Web Apps IIS setting not loading the user profile as mentioned here. I have enabled this by setting WEBSITE_LOAD_USER_PROFILE = 1 in the Azure portal app settings. I have tried with this update when running the code both via the WebJob and the Web App in Azure but I still receive the same error.
I used a decompiler to take a look under the hood at what the CngKey.Import method was actually doing. It looks like it tries to insert the certificate I am using into the "Microsoft Software Key Storage Provider". I don't actually need this, just need to read the value of the certificate but it doesn't look like that is possible.
Once I realized a certificate is getting inserted into a store somewhere one the machine, I started thinking about how bad of a think that would be from a security standpoint if your Azure Web App was running in a shared environment, like it does for the Free and Shared tiers. Sure enough, my VM was on the Shared tier. Scaling it up to the Basic tier resolved this issue.

Jasypt StandardPBEStringEncryptor setting password in spring bean configuration file

When using Jasypt's StandardPBEStringEncryptor we have to set password explicitly in spring bean configuration file. Is it ok and secure to have the password in the bean configuration file? Will it be a problem in PCI Compliance to store the encryptor password?
This will not be PCI compliant. Data encrypting keys cannot be stored in plaintext. The specific point is 3.5.2 which is:
Examine system configuration files to
verify that keys are stored in
encrypted format, and that
key-encrypting keys are stored
separately from data-encrypting keys.
You would probably also have other issues around the key management area, such as 3.6.6 (Split knowledge and dual control of keys)
Verify that key-management procedures
are implemented to require split
knowledge and dual control of keys
(for example, requiring two or three
people, each knowing only their own
part of the key, to reconstruct the
whole key).
Key management is the most challenging part of PCI compliance. You may want to consider using a (already PCI compliant) 3rd party to manage your card data. If you are rolling your own then I would advise that you bring in the assistance of a QSA (PCI Qualified Security Assesor) at the earliest opportunity to evaluate the security you're planning on implementing. ultimately it will be the QSA that you need to convince in order to pass your PCI requirements, and they will be more than happy to advise.
You need to store the symmetric key somewhere. A configuration file is a good place, as long as no one has access to it.
I have an idea
you can encrypt all of your plain password with keyPair of keystore.jks. You know that the keystore.jks has its own password. you can remember that password and when your program get started enter it on console. for example when your program start:
Console console = System.console();
keyPair = loadKeystore(new String(console.readPassword()));
private static KeyPair loadKeystore(String pwd) {
InputStream is = Main.class.getResourceAsStream("/keystore.jks");
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(is, s.toCharArray());
String alias = "youralias";
Key key = keystore.getKey(alias, pwd.toCharArray());
if (key instanceof PrivateKey) {
// Get certificate of public key
Certificate cert = keystore.getCertificate(alias);
// Get public key
PublicKey publicKey = cert.getPublicKey();
// Return a key pair
return new KeyPair(publicKey, (PrivateKey) key);
}
return null;
}
when you return the keypair you can uses it for encrypt your password.
key = loadKeystore("yourpass").getPrivate().getEncoded()
goodluck

Resources