How to generate or create private / public key in flutter? - dart

I need to generate a keypair in my Flutter app, There is one library called RSA which does parse a pair of public/private keys and is able to encrypt and decrypt strings using them, but it doesn't have the ability to generate a new KeyPair (preferably from a given string).
How can I generate the keys in the first place? Am I missing something?
//Future to hold our KeyPair
Future<crypto.AsymmetricKeyPair> futureKeyPair;
//to store the KeyPair once we get data from our future
crypto.AsymmetricKeyPair keyPair;
Future<crypto.AsymmetricKeyPair<crypto.PublicKey, crypto.PrivateKey>> getKeyPair()
{
var helper = RsaKeyHelper();
return helper.computeRSAKeyPair(helper.getSecureRandom());
}

It's easy using the fast_rsa package:
import 'package:fast_rsa/fast_rsa.dart';
KeyPair keyPair1 = await RSA.generate(2048);
print(keyPair1.privateKey);
print(keyPair1.publicKey);
https://pub.dev/packages/fast_rsa

Related

Generate Keypair in Kotlin Multiplatform

I am new to KMM, but trying to port a standard android app written in Java to KMM.
So, I have the following method:
private static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DSA");
keyPairGen.initialize(2048);
KeyPair pair = keyPairGen.generateKeyPair();
return pair;
}
With the keypair, I am going to sign a byte array and send the signature together with the public key to a java server, think of it as a variant of FIDO2.
Converting to Kotlin was not the problem, but then the java.security.* classes are used, which seems wrong when having in mind that there should also be an iOS variant. So my idea was to have in commonMain a function which would receive the byte array to be signed and returns an object containing the signature and the publickey for verification, in androidMain then the actual implementation for doing this with the code above - but how to do this for iosMain ? I can't figure out how to generate a keypair for signing using pure Kotlin for ios...

Create signature using Pkcs11Interop without token password

I'm using the Pkcs11Interop in combination with a certificate on a usb stick to sign pdf documents.
The following steps are executed to sign a document:
Load the pkcs11 library (LoadPkcs11Library)
Get a slot of the selected smartcard/usb token
OpenSession on the slot (Requires the slot pin)
Perform login on the session
Search the private key handle
sign the document (Requires the pin)
Corresponding code:
private byte[] GetSignatureFromHashViaPkcs11(byte[] hash, string pin)
{
Pkcs11InteropFactories factories = new Pkcs11InteropFactories();
using (IPkcs11Library pkcs11Library = factories.Pkcs11LibraryFactory.LoadPkcs11Library(factories, PKCS11LibPath, AppType.SingleThreaded))
{
ISlot slot = LoadSlot(pkcs11Library, CertificateToUse.BelongsToSmartCardSlot.TokenSerial);
using (ISession session = slot.OpenSession(SessionType.ReadOnly))
{
session.Login(CKU.CKU_USER, pin);
//Search the private key based on the pulblic key CKA_ID
IObjectHandle keyHandle = null;
var searchTemplate = new List<IObjectAttribute>()
{
//CKO_PRIVATE_KEY in order to get handle for the private key
session.Factories.ObjectAttributeFactory.Create(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY),
//CKA_ID searching for the private key which matches the public key
session.Factories.ObjectAttributeFactory.Create(CKA.CKA_ID, CertificateToUse.PublicKeyCKAID.GetValueAsByteArray()),
};
//filter the search result. Since we search for a private key, only one is returned for each certificate
var search = session.FindAllObjects(searchTemplate);
keyHandle = search.FirstOrDefault();
if (keyHandle == null || (keyHandle.ObjectId == CK.CK_INVALID_HANDLE))
{
throw new Exception("Unable to read SmartCard KeyHandle. Make sure the correct PKCS11 Library is used");
}
try
{
//Create the signature (using the pin)
var pinAsByteArray = UTF8Encoding.UTF8.GetBytes(pin);
using (IMechanism mechanism = session.Factories.MechanismFactory.Create(CKM.CKM_SHA256_RSA_PKCS))
return session.Sign(mechanism, keyHandle, pinAsByteArray, hash);
}
catch (Exception ex)
{
throw new Exception("Error creating the signature", ex);
}
}
}
}
This solution works if the slot pin and the private key pin are the same.
In case those pins are different the above code doesn't work since only one pin is used.
If i manage the slot pin and private key pin manually in code, everything works.
But it seems it should be possible to create a signature without having to perform an OpenSession before.
My customer has an old tool which does only require the private key pin in order to sign a document (Which means it is technically possible to sign without having the slot pin).
My problem is that i currently require to do the session.Login with the slot pin in order to get the private key handle.
Question: Is there another way of signing a document using Pkcs11Interop without having to first do a session.Login. Or is there another way of getting the private key handle without having to first do a session.Login?
If the customer is not willing to trust you with the slot pin perhaps you can build an intermediate adaptor service which in turn can perform the signing and publishes this capability as an api with some authentication that you can pass the payload into and it will sign and return it.
The client would then be free to manage the intermediate component and initialise it with slot pin.

Azure web app with access to multiple key vaults

I'm wondering if an Azure web application can have access to multiple key vaults? This is because one of our web applications has multiple database connection strings and each of the databases has columns encrypted with always encrypted and the column encryption keys will be stored in their own key vaults per database. If this is possible, how does the web application know which key vault to access to get the column encryption key for the respective database it's connecting to?
Currently the web application has access to one key vault and all of the databases are encrypted with the same column encryption key which is in this key vault. But I want to split this out so each database has it's own key vault and respective column encryption key for better security. The web application obtains access to the key vault via Azure Active Directory with the client id and secret mechanism. I've played around with adding the Azure Active Directory application to the multiple key vaults using the key vault access policy but not sure if this is correct/will work.
The code I'm using to wire up the column encryption key with the web application (which appears to be key vault agnostic):
public static void InitializeAzureKeyVaultProvider()
{
var clientId = ConfigurationManager.AppSettings["AuthClientId"];
var clientSecret = ConfigurationManager.AppSettings["AuthClientSecret"];
_clientCredential = new ClientCredential(clientId, clientSecret);
SqlColumnEncryptionAzureKeyVaultProvider azureKeyVaultProvider =
new SqlColumnEncryptionAzureKeyVaultProvider(GetToken);
Dictionary<string, SqlColumnEncryptionKeyStoreProvider> providers =
new Dictionary<string, SqlColumnEncryptionKeyStoreProvider>
{
{SqlColumnEncryptionAzureKeyVaultProvider.ProviderName, azureKeyVaultProvider}
};
SqlConnection.RegisterColumnEncryptionKeyStoreProviders(providers);
}
private static async Task<string> GetToken(string authority, string resource, string scope)
{
var authContext = new AuthenticationContext(authority);
var result = await authContext.AcquireTokenAsync(resource, _clientCredential);
if (result == null)
{
throw new InvalidOperationException("Failed to obtain the access token");
}
return result.AccessToken;
}
Thoughts?

How to store Public Certiticate (.cer file) in Azure Key Vault

How I can upload or store public key (.cer) file in azure keyvault. From the keyvault panel it gives error when I tried to to upload any .cer file where It works for .pfx file.
Loading Public Key Certificates
Azure Key Vault Explorer allows you to load public key certificates (.cer files).
Certificates are stored as keys in the Key Vault using a "standard" format used by that application (since .cer files aren't natively supported by Azure Key Vault).
Accessing Public Key Certificates
Once you have loaded public keys into the Azure Key Vault, they can then be accessed programatically as follows:
// load certificate based on format used by `Azure Key Vault Explorer`
var azureServiceTokenProvider = new AzureServiceTokenProvider();
var kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
var certBundle = await kv.GetSecretAsync(secretIdentifier).ConfigureAwait(false);
byte[] certBytes = null;
if (certBundle.ContentType == "application/x-pkcs12")
{
certBytes = Convert.FromBase64String(certBundle.Value);
}
else if (certBundle.ContentType == "application/pkix-cert")
{
certBytes = certBundle?.Value.FromJson<PublicKeyCertificate>()?.Data;
}
if (certBytes != null && certBytes.Length > 0)
{
return new X509Certificate2(certBytes,
"",
X509KeyStorageFlags.Exportable |
X509KeyStorageFlags.MachineKeySet |
X509KeyStorageFlags.PersistKeySet);
}
return null;
...
// class used to access public key certificate stored in Key Vault
public class PublicKeyCertificate
{
public byte[] Data;
}
You should consider if Key Vault is the appropriate solution for your scenario. The public key (by nature) is not confidential data, you don't need a secure place to store it. You can use a general purpose storage service for it.
If you still need to use Key Vault, you can store it as a secret. Key Vault secrets are octet sequences with a maximum size of 25k bytes each.

How do I generate an encryption hash in ASP.NET MVC?

I am looking into creating a custom members login system (for learning) and I haven't been able to figure out the C# command to generate an encrypted hash.
Is there a certain namespace I need to import or anything like that?
Using the namespace System.Security.Cryptography:
MD5 md5 = new MD5CryptoServiceProvider();
Byte[] originalBytes = ASCIIEncoding.Default.GetBytes(originalPassword);
Byte[] encodedBytes = md5.ComputeHash(originalBytes);
return BitConverter.ToString(encodedBytes);
or FormsAuthentication.HashPasswordForStoringInConfigFile method
For my part, I purpose this function i use to get the gravatar picture profil:
you can use it like you want
public string getGravatarPicture()
{
MD5 md5 = new MD5CryptoServiceProvider();
Byte[] originalBytes = ASCIIEncoding.Default.GetBytes(email.ToLower());
Byte[] encodedBytes = md5.ComputeHash(originalBytes);
string hash = BitConverter.ToString(encodedBytes).Replace("-", "").ToLower();
return "http://www.gravatar.com/avatar/"+hash+"?d=mm";
}
Well, first of all an encryption hash is a contradiction. Like a vegetarian steak. You can use encryption, or you can hash them (and you should hash them), but hashing is not encryption.
Look up a class starting with Md5 ;) Or Sha1 - those are hash algoryithms. It is all there in .NET (System.Security.Cryptography namespace).
I prefer having my hash all in one concatenated string. I borrowed this to build my hash:
public static string MD5Hash(string itemToHash)
{
return string.Join("", MD5.Create().ComputeHash(Encoding.ASCII.GetBytes(itemToHash)).Select(s => s.ToString("x2")));
}

Resources