Calculating the public key token from a pfx file - code-signing

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

Check if redis key is hash or string using restTemplate

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.

Laravel Encryption error with custom generated key

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.

Spring Framework and encode/decode of public key

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.

C# Xamarin ; Private key - store and retrieve

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?

How to cast "byte[] publicKey" to "Data Object" (to use ObjectHandle)

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?

Resources