I would like to calculate the public key token from a pfx file and make sure that it matches the public key token of a signed assembly, but I keep running into the following issues and would love some help on how to fix it.
From within the signed assembly, I use the following code to get the public key and the public key token:
Console.WriteLine("Public Key: {0}{1}", System.BitConverter.ToString(System.Reflection.Assembly.GetExecutingAssembly().GetName().GetPublicKey()), Environment.NewLine);
Console.WriteLine("Public Key Token: {0}{1}", System.BitConverter.ToString(System.Reflection.Assembly.GetExecutingAssembly().GetName().GetPublicKeyToken()), Environment.NewLine);
And the result is the following:
Public Key: 00-24-00-00-04-80-00-00-94-00-00-00-06-02-00-00-00-24-00-00-52-53-41-31-00-04-00-00-01-00-01-00-31-71-7C-0A-A5-A0-76-6D-EF-44-BD-F6-6F-7B-BA-C2-8F-8B-8D-09-98-8D-A6-B5-5A-C6-24-96-34-13-A0-40-5D-78-89-1C-A4-4F-B4-09-11-5C-5F-97-2C-E3-AD-A7-B1-19-41-38-25-B1-21-9F-6C-6B-DA-D5-1D-62-75-A6-25-D1-04-10-CC-A0-32-9B-A1-C9-BA-3A-DA-A5-06-F9-7F-00-02-E9-3F-46-EE-C5-DC-1E-C6-95-13-49-25-F3-E5-0D-67-35-93-0D-4C-84-89-D7-36-96-00-66-74-52-09-F4-A2-4D-2C-72-85-20-44-88-9C-B1-EE-C0-21-CE
Public Key Token: 0C-C2-5B-D7-34-42-06-3D
If I use the value of the Public Key noted above, I can recalculate the Public Key Token myself in Powershell:
$assemblyPublicKeyString = “00-24-00-00-04-80-00-00-94-00-00-00-06-02-00-00-00-24-00-00-52-53-41-31-00-04-00-00-01-00-01-00-31-71-7C-0A-A5-A0-76-6D-EF-44-BD-F6-6F-7B-BA-C2-8F-8B-8D-09-98-8D-A6-B5-5A-C6-24-96-34-13-A0-40-5D-78-89-1C-A4-4F-B4-09-11-5C-5F-97-2C-E3-AD-A7-B1-19-41-38-25-B1-21-9F-6C-6B-DA-D5-1D-62-75-A6-25-D1-04-10-CC-A0-32-9B-A1-C9-BA-3A-DA-A5-06-F9-7F-00-02-E9-3F-46-EE-C5-DC-1E-C6-95-13-49-25-F3-E5-0D-67-35-93-0D-4C-84-89-D7-36-96-00-66-74-52-09-F4-A2-4D-2C-72-85-20-44-88-9C-B1-EE-C0-21-CE”.replace(‘-’,’’)
$assemblyPublicKey = New-Object byte[] ($assemblyPublicKeyString.length/2)
$assemblyPublicKey = [byte[]] -split ($assemblyPublicKeyString -replace '..', '0x$& ')
$csp = [System.Security.Cryptography.SHA1CryptoServiceProvider]::New()
$myHash = $csp.ComputeHash($assemblyPublicKey)
$myPKT = New-Object byte[] 8
for ($i = 0; $i -le ($myPKT.length - 1); $i++) { $myPKT[$i] = $myHash[$myHash.length - $i - 1]; }
[System.BitConverter]::ToString($myPKT)
The output is:
0C-C2-5B-D7-34-42-06-3D
Now, if I use the pfx file that I used to sign the assembly above, I seem to have no way to get to the same Public Key value. Here is the closest I've managed to come:
$mypwd2 = ConvertTo-SecureString -String "atempkeytotest22" -Force -AsPlainText
$mypfx = Get-PfxData -FilePath .\atempkeytotest2.pfx -Password $mypwd2
$cspBlob = $mypfx.EndEntityCertificates[0].PublicKey.Key.ExportCspBlob($false)
$snk = [System.Reflection.StrongNameKeyPair]::New($cspBlob)
[System.BitConverter]::ToString($snk.PublicKey)
And this results in the following public key:
00-A4-00-00-04-80-00-00-94-00-00-00-06-02-00-00-00-A4-00-00-52-53-41-31-00-04-00-00-01-00-01-00-31-71-7C-0A-A5-A0-76-6D-EF-44-BD-F6-6F-7B-BA-C2-8F-8B-8D-09-98-8D-A6-B5-5A-C6-24-96-34-13-A0-40-5D-78-89-1C-A4-4F-B4-09-11-5C-5F-97-2C-E3-AD-A7-B1-19-41-38-25-B1-21-9F-6C-6B-DA-D5-1D-62-75-A6-25-D1-04-10-CC-A0-32-9B-A1-C9-BA-3A-DA-A5-06-F9-7F-00-02-E9-3F-46-EE-C5-DC-1E-C6-95-13-49-25-F3-E5-0D-67-35-93-0D-4C-84-89-D7-36-96-00-66-74-52-09-F4-A2-4D-2C-72-85-20-44-88-9C-B1-EE-C0-21-CE
As you can see it differs in two bytes, in what appears to be a header. (The A4s in the beginning.)
00-A4-00-00-04-80-00-00-94-00-00-00-06-02-00-00-00-A4-00-00-...
I've tried this with several different keys. Because the public key token is a hash, it prevents me from calculating and comparing the two public key tokens.
How do I rectify this, and do you know the meaning of these values?
Related
I have Redis DB consisting of hashes and strings.
I got all keys from DB using this code:
Set<byte[]> keys = redisTemplate.getConnectionFactory().getConnection().keys("*".getBytes());
Iterator<byte[]> it = keys.iterator();
while(it.hasNext()){
byte[] data = (byte[])it.next();
String key = (new String(data, 0, data.length));
System.out.println(key);
}
from here: How to get all Keys from Redis using redis template
Since the key can be hash or string, how to determine when I can use opsForHash and opsForValue i.e. how to check if it is hash or it is a string in spring boot using restTemplate.
The Redis command to get the type of a key is TYPE: https://redis.io/commands/type
You can use RedisTemplate's public DataType type(K key) method to execute this: https://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/RedisTemplate.html#type-K-
Here's an example:
Set<byte[]> keys = redisTemplate.getConnectionFactory().getConnection().keys("*".getBytes());
Iterator<byte[]> it = keys.iterator();
while(it.hasNext()){
byte[] data = (byte[])it.next();
String key = (new String(data, 0, data.length));
DataType type = redisTemplate.type(key);
if (type == DataType.HASH) {
// ...
} else if (type == DataType.STRING) {
// ...
}
}
Edit: one more piece of advice is that you may want to use SCAN instead of KEYS * (mentioned in one answer to the SO question you linked). Scan is generally better in production since it doesn't try to get and return all keys at once.
I have generated a unique custom key and need to encrypt a value using this key.Its return error
The only supported ciphers are AES-128-CBC and AES-256-CBC with the
correct key lengths.
public function test(){
$key = $this->generateRandomKey();
$newEncrypter = new \Illuminate\Encryption\Encrypter( $key, Config::get('app.cipher') );
echo $encrypted = $newEncrypter->encrypt( 'hello' );
}
protected function generateRandomKey()
{
return 'base64:'.base64_encode(
Encrypter::generateKey(Config::get('app.cipher'))
);
}
Late to the party, but posting it here as that might help someone some day.
The Key should be of 32 character long if AES-256-CBC is used and 16 character if AES-128-CBC is being used.
From vendor\laravel\framework\src\Illuminate\Encryption\Encrypter.php you can see:
public static function supported($key, $cipher)
{
$length = mb_strlen($key, '8bit');
return ($cipher === 'AES-128-CBC' && $length === 16) ||
($cipher === 'AES-256-CBC' && $length === 32);
}
For Encrypting/Decrypting using custom Key, you can use the following snippet.
$theOtherKey = "22222222222222222222222222222222"; //32 character long
$text = 'Hello World'; //or the text that you want to encrypt.
$newEncrypter = new \Illuminate\Encryption\Encrypter ($theOtherKey,'AES-256-CBC');
$encrypted = $newEncrypter->encrypt($text);
echo $encrypted;
If you prefer using AES-128-CBC, ensure your $theOtherKey is 16 character long.
You should not base 64 encode the key (such as you are doing in generateRandomKey), if I'm reading the API correctly - and I presume I am because the errors match.
I am trying to create a new RsaVerifier to check a public key:
JwtHelper.decodeAndVerify(token, verifier);
I do believe it's a valid public key. I'm copying it correctly from my browser. It does begin with a return character though. It actually has them in several places:
-----BEGIN PUBLIC KEY-----\nMIIBI.....
It fails when creating an RsaVerifier.
SignatureVerifier verifier = null;
if (key.startsWith("-----BEGIN PUBLIC KEY-----")) {
logger.log("Trying to get key verifier...");
verifier = new RsaVerifier(key); //FAILS HERE
...
Specifically, it's failing on the last line in this snippet from RsaKeyHelper:
private static Pattern PEM_DATA = Pattern.compile("-----BEGIN (.*)-----(.*)-----END (.*)-----", Pattern.DOTALL);
static KeyPair parseKeyPair(String pemData) {
Matcher m = PEM_DATA.matcher(pemData.trim());
if (!m.matches()) {
throw new IllegalArgumentException("String is not PEM encoded data");
}
String type = m.group(1);
final byte[] content = b64Decode(utf8Encode(m.group(2))); //FAILS HERE
with error:
Exception validating token :
org.springframework.security.jwt.codec.InvalidBase64CharacterException: Bad
Base64 input character decimal 92 in array position 0
I know decimal 92 is a forward slash and I have one in position 0, in fact. However, I've tried removing the return characters and it doesn't recognize it as valid. Here's a link to the RsaKeyHelper class:
https://www.programcreek.com/java-api-examples/index.php?source_dir=spring-security-oauth-master/spring-security-jwt/src/main/java/org/springframework/security/jwt/crypto/sign/RsaKeyHelper.java
I am struggling to figure out how I can pass this key as a string that is accepted.
I have an issue with retrieving Private key from X509Storage after restart of application.
I am working with:
Storage
Certificate
My process:
1 Create storage
Storage = new X509Store(StoreName.TrustedPublisher,
StoreLocation.CurrentUser);
Storage.Open(OpenFlags.ReadWrite);
2 Create Certificate with Private key
Cert = new X509Certificate2(
Convert.FromBase64String("...my certificate..."),
"",
X509KeyStorageFlags.UserKeySet |
X509KeyStorageFlags.PersistKeySet |
X509KeyStorageFlags.Exportable);
var privateKey = new RSACryptoServiceProvider();
privateKey.FromXmlString("...my private key relevant to certificate...");
privateKey.PersistKeyInCsp = true;
Cert.PrivateKey = privateKey;
3 Insert Certificate to storage
Storage.Add(Cert);
4 Verify, that Certificate with Private key is in storage
var certs = Storage.Certificates;
foreach (var cert in certs)
{
CertsView.Append("Name: " + cert.Subject + "; Has PK: "+ cert.HasPrivateKey + "\n");
}
5 Restart application and verify again
I am able to retrieve certificate, which I have inserted.
However, certificate is without private key at this point.
What I am missing?
I'm extracting the Public key for encryption from the sender's Certificate as byte[] array
JObject o = JObject.Parse(reply);
string certResponse = o.GetValue("certificate").Value<string>();
byte[] certByteArray = Encoding.ASCII.GetBytes(certResponse);
//Extract Public key from Certificate
var certTest = new X509Certificate2(certByteArray);
var certPublicKey = certTest.GetPublicKey();
I wish to use PKCS11Interop Encrypt() function which takes ObjectHandle of the key to Encrypt message/data. The only way I find is to set ObjectAttributes and session.CreateObject(objectAttributes); and eventually DestroyObject.
However I get CKR_FUNCTION_NOT_SUPPORTED calling CreateObject(). As clarified by jariq in this post that OpenSC PKCS#11 library does not support/implement some functions defined in PKCS#11 specification, What is the alternative/workaround to use the byte array publicKey for encryption?