How to retrieve the private keys from keycloack realms keys? - private-key

I am trying to get private keys from keycloack realms keys .
I am able to get public keys using
Open-id/certs api.please let me know if able to get private keys of realms in keycloack.

I use the private key, to write tests to tamper the JWT payload to verify an application. I got all securiy pitfalls 😀
Getting private key with MySQL is easy:
use <kc_db_schema>;
SELECT VALUE FROM COMPONENT_CONFIG CC INNER JOIN COMPONENT C INNER JOIN REALM R ON(CC.COMPONENT_ID = C.ID AND R.ID = C.REALM_ID)
WHERE R.NAME='your-realm-name' AND C.NAME = 'rsa-generated' AND CC.name = 'privateKey';
Using this privateKey value I'm able to sign my payload.
In Python PyJWT it is VERY important to add the '-----BEGIN RSA PRIVATE KEY-----' / '-----END RSA PRIVATE KEY-----' with linefeeds to the key:
private_key = b"-----BEGIN RSA PRIVATE KEY-----\n<my privateKey from SQL query>\n-----END RSA PRIVATE KEY-----"
jwt_encoded = jwt.encode({my payload}, private_key, algorithm="RS256")

Well, you are not allowed to. That is why they are called private keys, you can't expect a private key through API.
Private keys are private to the holder, you can learn more about them here.

I am able to get private keys from keycloack database and table name is component_config.

Related

Best way to Store an X509Certificate2 object with it's privateKey into the CertStore

I have generated a CSR, and had it signed. I still have the private key that I used to create the CSR, and I want to store that cert in the Windows CertStores, along with that private key.
My metric for success is:
When I view the cert in the CertStore, it is marked as having a private key. Specifically, it has the little 'key' sub-icon in the top left of the cert icon, and if you open the cert up, it says "You have a private key that corresponds to this certificate" under the ValidDates info.
We initially assumed that .CopyWithPrivateKey(RSA key) would do that for us, but it doesn't seem to work on it's own. We also need to set some keyStorage flags, but we can only do that by .Export()ing the cert to a byte[] array and then "importing" it with another constructor call.
I've tried a bunch of variations, and that's the only sequence of events that works:
public void InstallCertOnNonUiThread(byte[] certificateDataFromCsrResponse, RSA privateKeyUsedToGenerateCsr)
{
var keyStorageFlags = X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet;
var originalCert = new X509Certificate2(certificateDataFromCsrResponse);
var exportOfOriginalCert = originalCert.Export(X509ContentType.Pkcs12);
var withFlagsCert = new X509Certificate2(certificateDataFromCsrResponse, (SecureString)null, keyStorageFlags);
var exportOfWithFlagsCert = withFlagsCert.Export(X509ContentType.Pkcs12);
var copiedWithPKCert = originalCert.CopyWithPrivateKey(privateKeyUsedToGenerateCsr);
var exportOfCopiedWithPkCert = copiedWithPKCert.Export(X509ContentType.Pkcs12);
var withFlagsReimportOfOriginal = new X509Certificate2(exportOfOriginalCert, (SecureString)null, keyStorageFlags);
var withFlagsReimportOfWithFlags = new X509Certificate2(exportOfWithFlagsCert, (SecureString)null, keyStorageFlags);
var withFlagsReimportOfCopiedWithPK = new X509Certificate2(exportOfCopiedWithPkCert, (SecureString)null, keyStorageFlags);
InstallCertInStore(StoreLocation.LocalMachine, originalCert); // Doesn't work; no key in Store UI.
InstallCertInStore(StoreLocation.LocalMachine, withFlagsCert); // Doesn't work; no key in Store UI.
InstallCertInStore(StoreLocation.LocalMachine, copiedWithPKCert); // Doesn't work; no key in Store UI.
InstallCertInStore(StoreLocation.LocalMachine, withFlagsReimportOfOriginal); // Doesn't work; no key in Store UI.
InstallCertInStore(StoreLocation.LocalMachine, withFlagsReimportOfWithFlags); // Doesn't work; no key in Store UI.
InstallCertInStore(StoreLocation.LocalMachine, withFlagsReimportOfCopiedWithPK);// This one works. Cert has key icon, and text "You have a private key that corresponds to this certificate"
}
private static void InstallCertInStore(StoreLocation location, X509Certificate2 newCert)
{
using (var store = new X509Store(StoreName.My, location))
{
store.Open(OpenFlags.ReadWrite);
store.Add(newCert);
}
}
So my final code to do this will look like:
public Task<bool> InstallCertOnNonUiThread(byte[] certificateDataFromCsrResponse, RSA privateKeyUsedToGenerateCsr, string orgId)
{
var keyStorageFlags = X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet;
var originalCert = new X509Certificate2(certificateDataFromCsrResponse);
var copiedWithPKCert = originalCert.CopyWithPrivateKey(privateKeyUsedToGenerateCsr);
var exportOfCopiedWithPkCert = copiedWithPKCert.Export(X509ContentType.Pkcs12);
var withFlagsReimportOfCopiedWithPK = new X509Certificate2(exportOfCopiedWithPkCert, (SecureString)null, keyStorageFlags);
InstallCertInStore(StoreLocation.LocalMachine, withFlagsReimportOfCopiedWithPK);// This one works. Cert has key icon, and text "You have a private key that corresponds to this certificate"
return Task.FromResult(true);
}
That final option does work, but it seems like way more steps than ought to be necessary, and it suggests that I'm about to define my own extention method: .ActuallyCopyWithPrivateKey, to replace the .NET framework version of that method. Which seems wrong.
Is there a better way to be achieving this, or does it really need all 4 steps.
CopyWithPrivateKey maintains the state of the private key. If it's an ephemeral key, it stays ephemeral. If it's a persisted key, it stays persisted. When you created the RSA privateKeyUsedToGenerateCsr object you created an ephemeral key object, and so you got the behavior you see.
Your 4-liner is correct (except you really want each of the cert objects in a using statement).
Hydrate the newly signed certificate into an X509Certificate2 object
CopyWithPrivateKey makes a new X509Certificate2 object with the private key bound (could be persisted, could be ephemeral).
Exporting as a PFX can fail if the key is persisted and non-exportable. It's up to you if you want to guard against this, or not. Otherwise, this creates the possibility of reimporting the key to a persisted key more easily.
Reimporting the PFX with PersistKeySet makes a new copy of the private key (if it was already persisted, or "the first copy" if it was ephemeral), and makes it so the key isn't erased when the cert object gets garbage collected or disposed.
On the other hand, you could create the key as a persisted key and just need to use CopyWithPrivateKey once. Of course, this notion only exists on Windows.
Creating a persisted CNG key
Assuming you created the key as new RSACng(2048) or RSA.Create(2048), you can make a persisted key by
CngKeyCreationParameters keyParameters = new CngKeyCreationParameters
{
// Or whatever.
ExportPolicy = CngExportPolicies.None,
// If applicable.
KeyCreationOptions = CngKeyCreationOptions.MachineKey,
Parameters =
{
new CngProperty("Key Length", BitConverter.GetBytes(2048), CngPropertyOptions.Persist),
},
};
using (CngKey key = CngKey.Create(CngAlgorithm.Rsa, Guid.NewGuid().ToString(), keyParameters))
{
return new RSACng(key);
}
Creating a persisted CAPI key
Ideally, don't. Create a persisted CNG instead. But, if you must:
Assuming you created the key as new RSACryptoServiceProvider(2048), you can make a persisted CAPI key by
CspParameters cspParams = new CspParameters
{
KeyContainerName = Guid.NewGuid().ToString(),
Flags =
// If appropriate
CspProviderFlags.UseMachineKeyStore |
// If desired
CspProviderFlags.UseNonExportableKey
};
return new RSACryptoServiceProvider(2048, cspParams);

How to Access OQL Query on a Gemfire 9.6 Region in java

I am using Gemfire pivotal for the first time and I need someone who can help me with below question. The Gemfire Pivotal 9.6 is installed on Unix server and I am able to connect to Unix with no issue. I am inside unix now, but I can't access Gemfire.
Q. How to Access OQL Query on a Gemfire 9.6 Region in java.
This is the way I connected to Unix.
private String host = "host name went here";
private String port = " port number here";
private String user = "userID";
private String password = "password"
private String SSH command = "ssh ------"
private String commandBah = "bash";
private String commandgfish = "sh /data/gemfire9.6/pivotal-gemfire-9.6.0/bin/gfsh";
This is the way I am trying to connect to Gemfire which is not working properly now.
// Gemfire Connection URL, username and password
private String connect To Gemfire = "connect --locator=--------";
private String username = "credential";--
private String command Pass = "password"
private String comman Setvariable = "set variable --name=APP_RESULT_VIEWER --value=EXTERNAL";
To access a region in java, you need to create a GemFire client. Here's a basic java snippet that creates a GemFire client and execute a query:
ClientCache cache = new ClientCacheFactory()
.addPoolLocator(locator_host, 10334)
.create()
cache.getQueryService().newQuery("select count(*) from /region").execute()
For a more complete example, you can take a look at the geode examples project (GemFire is based on Geode). Here's an example of querying from the client: https://github.com/apache/geode-examples/tree/master/indexes

Decode(Base64) and Decrypt(AES/CBC/PKCS5PADDING) with CryptoJS - React

I am working on the web application using react as front-end and spring mvc as back-end. I need to store some user information in local storage of the browser. I do not want to store that info in local storage as a plain text. So I thought to go for AES encryption at server side and pushing those data back to JS side. For that I need client side decryption framework. I found crypto-js as very useful for all these things. I am not able to understand where I am lacking at client side to decrypt and decode.
I am explaining my Spring Side Encryption Code first which is absolutely fine:
public class EncryptDecrypt {
private static final String SECRET_KEY_1 = "ssdkF$HUy2A#D%kd";
private static final String SECRET_KEY_2 = "weJiSEvR5yAC5ftB";
private IvParameterSpec ivParameterSpec;
private SecretKeySpec secretKeySpec;
private Cipher cipher;
public EncryptDecrypt() throws UnsupportedEncodingException, NoSuchPaddingException, NoSuchAlgorithmException {
ivParameterSpec = new IvParameterSpec(SECRET_KEY_1.getBytes("UTF-8"));
secretKeySpec = new SecretKeySpec(SECRET_KEY_2.getBytes("UTF-8"), "AES");
cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
}
public String encrypt(String toBeEncrypt) throws NoSuchPaddingException, NoSuchAlgorithmException,
InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] encrypted = cipher.doFinal(toBeEncrypt.getBytes());
return Base64.encodeBase64String(encrypted);
}
}
At the client side, I am not able to decode and decrypt the code with simple things. Here is my client side code:
var CryptoJS = require("crypto-js");
var data = "Ggydx4oA1+SKBw+unA8BUUm2tnvkQbp1terdF2PEGFYSEZL/ye08op/0b0BauGtIl1dBIodrlKXo2de3MykYmocd3ctxFtIIki01V+M8XeQj6B384o0G+H7NpVx5tCJjPDvdqVRObtxCTqu3r8QRzYTNcMM5bRhbYxCYl8/NRyPQJnmcJDlRBeVOoJiQNA7Qd5UJD/mNivoyMUfYGV7/DlpylQWWwEAHVdgcb865i8jnf3vqURehAXYoaD6Bgodi1EM4H007uv0o6NEOk3H4jQ==";
var key = "weJiSEvR5yAC5ftB";
// Decode the base64 data so we can separate iv and crypt text.
var rawData = atob(data);
var iv = "ssdkF$HUy2A#D%kd";
var crypttext = rawData.substring(16);
console.log(rawData);
// Decrypt...
var plaintextArray = CryptoJS.AES.decrypt(
{ ciphertext: CryptoJS.enc.Base64.parse(crypttext) },
key,
{ iv: iv }
);
console.log(plaintextArray);
console.log(CryptoJS.enc.Base64.stringify(plaintextArray));
var decryptedData = JSON.parse(CryptoJS.enc.Base64.stringify(plaintextArray).toString(CryptoJS.enc.Utf8));
console.log(decryptedData);
P.S: I have sent JSON to client side and so that I am parsing it in the end. I am newbie for encryption and decryption. I am really stuck with what my client side code should look a like. Please help.
You shouldn't pass string as key in CryptoJS. In this case it considers this string not as key, but as password. And generate key from password by using PBKDF. Working example below:
var data = "Ggydx4oA1+SKBw+unA8BUUm2tnvkQbp1terdF2PEGFYSEZL/ye08op/0b0BauGtIl1dBIodrlKXo2de3MykYmocd3ctxFtIIki01V+M8XeQj6B384o0G+H7NpVx5tCJjPDvdqVRObtxCTqu3r8QRzYTNcMM5bRhbYxCYl8/NRyPQJnmcJDlRBeVOoJiQNA7Qd5UJD/mNivoyMUfYGV7/DlpylQWWwEAHVdgcb865i8jnf3vqURehAXYoaD6Bgodi1EM4H007uv0o6NEOk3H4jQ==";
var rawData = CryptoJS.enc.Base64.parse(data);
var key = CryptoJS.enc.Latin1.parse("weJiSEvR5yAC5ftB");
var iv = CryptoJS.enc.Latin1.parse("ssdkF$HUy2A#D%kd");
var plaintextData = CryptoJS.AES.decrypt(
{ ciphertext: rawData },
key,
{ iv: iv });
var plaintext = plaintextData.toString(CryptoJS.enc.Latin1);
console.log(plaintext);
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.js"></script>
BTW, you shouldn't use the same IV every time. In this case you miss the base purpose of IV and CBC mode. Your overall security becomes equal to ECB mode.

.NetCore 2.2: How to get a private key of a certificate?

for the implementation of an API I use, I need to provide a certificate, which consists of 2 byte arrays one for the public key and the other one for private key.
My initial idea was to do this with X509Certificate object of .Net. But I am struggling to get the private key bytes.
var certificate = new X509Certificate2("testCert.pfx", password, X509KeyStorageFlags.Exportable);
byte[] myPublicKey = certificate.GetRawCertData();
byte[] privateKey = ???
I've tried to export the key, but I can't export the private key standalone.
And:
certificate.PrivateKey.ToXmlString(true);
is not available on a Ubuntu System :-(
Do you have any ideas, how to get the private bytes from certificates?
May be X509Certificate2 is not the best solution for this...
Use an approrpiate method of these X509Certificate2 extension methods:
GetRSAPrivateKey(X509Certificate2) -- for RSA keys
GetDSAPrivateKey(X509Certificate2) -- for DSA keys
GetECDsaPrivateKey(X509Certificate2) -- for EC keys
Extension method you need to use depends on asymmtric key algorithm.

Can I use KeyGenerator if encryptor and decryptor are in different application/server

I am working with encryption using AES. My customer is encrypting some of the sensitive data while posting the data to my web API. And my code will decrypt these fields before insert them to the database.
Originally we agree to use a fixed secret key. Below is the code:
public class AESEncryptor {
private static final String ALGO = "AES";
private static final String keyVal = "!5Po4#j82Adsu39/*na3n5";
public static String encrypt(String data) {
try {
Key key = genKey();
Cipher c = Cipher.getInstance(ALGO);
c.init(Cipher.ENCRYPT_MODE, key);
byte[] encVal = c.doFinal(data.getBytes());
return Base64.encodeBase64String(encVal);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String decrypt (String encryptedData) throws Exception{
Key key = genKey();
Cipher c = Cipher.getInstance(ALGO);
c.init(Cipher.DECRYPT_MODE, key);
byte[] data = Base64.decodeBase64(encryptedData);
byte[] decByptes = c.doFinal(data);
return new String(decByptes);
}
private static Key genKey() throws Exception {
fixKeyLength();
return new SecretKeySpec(keyVal.getBytes(), ALGO);
}
}
Then the other party suggested we should switch to KeyGenerator to generate a random secure key. Something like the following.
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256);
SecretKey key = keyGen.generateKey();
final byte[] nonce = new byte[32];
SecureRandom random = SecureRandom.getInstanceStrong();
random.nextBytes(nonce);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec spec = new GCMParameterSpec(16 * 8, nonce);
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
I am not sure that is possible. Because the correct decryption relies on the same key for encryption. If the key is random, how would my API know what key to use every time? Or is there a solution to handle this situation?
There is no solution to handle this problem. Symmetric encryption requires that both parties know the key in order to encrypt and decrypt. If the key is random each time, then you need a way to communicate the key.
The scheme you have designed is quite poor, since a fixed key means that the key being compromised will bring down the whole system. You're also using ECB mode, which is inherently insecure. No authentication either.
If you want to communicate data securely from one party to another, use TLS with client authentication. This is the industry standard way to solve this problem and you don't have to get your hands dirty with the crypto.

Resources