How can i use bouncy castle to extract modulus value from PrivateKeyInfo object? - cryptography

I am trying to get the modulus value of a private key using bouncy castle library. I was able to get PrivateKeyInfo object how can i get the modulus value from this?

You could do as follow (this code is for public key but yours should be similar)
PublicKey key = getPublicKey();
KeyFactory keyFac = KeyFactory.getInstance("RSA");
RSAPublicKeySpec pkSpec = keyFac.getKeySpec(key,
RSAPublicKeySpec.class);
byte[] modulusBytes = pkSpec.getModulus().toByteArray();
modulusBytes = stripLeadingZeros(modulusBytes);

Related

How do I know if my data was decrypted correctly?

Im using the Cipher class in the java.security library to encrypt and decrypt data. Im specifically using RSA encryption to encrypt AES parameters and message byte length, the AES cipher is what I'm using to encrypt the message itself. Currently I have a problem that I can't be sure if the provided encrypted AES parameters and message length were encrypted with my RSA key, or if they were encrypted at all and not just random jiberish.
val rsaCipher = Cipher.getInstance("RSA")
rsaCipher.init(Cipher.DECRYPT_MODE, privateKey)
val rsaDecoded = rsaCipher.doFinal(encryptedAesParametersAndMessageLength)
val aesParameters = ByteArray(48)
val messageLength = ByteArray(4)
for (i in aesParameters.indices) {
aesParameters[i] = rsaDecoded[i]
}
for (i in messageLength.indices) {
messageLength[i] = rsaDecoded[i + aesParameters.size]
}
val length = ByteBuffer.wrap(messageLength).order(ByteOrder.LITTLE_ENDIAN).int
val aesEncryptor = AesEncryptor(aesParameters)
//bytes of the encryptedMessage
//TODO Make sure this doesn't result in an error
val encryptedMessage = ByteArray(length)
When trying to decrypt AES parameters and message length using the RSA key it doesn't throw any kind of exception if the data wasn't decrypted correctly. Eventually this leads to a memory overflow error because the message length is too large. Is it safe to maybe put a 4 bytes(holding some constant int value) after these parameters that i can check to make sure the data was decrypted correctly, or would that risk my apps safety?

confused on validation of token on auth0 JWT java library

I read public/private key is so you can
create JWT token with private / public key
hand out your public key only to 3rd parties
3rd parties can now validate users JWT tokens via the public key
However, their example with private / public key requires the private key to validate which seems odd ->
String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.AbIJTDMFc7yUa5MhvcP03nJPyCPzZtQcGEp-zWfOkEE";
RSAPublicKey publicKey = //Get the key instance
RSAPrivateKey privateKey = //Get the key instance
try {
Algorithm algorithm = Algorithm.RSA256(publicKey, privateKey);
JWTVerifier verifier = JWT.require(algorithm)
.withIssuer("auth0")
.build(); //Reusable verifier instance
DecodedJWT jwt = verifier.verify(token);
} catch (JWTVerificationException exception){
//Invalid signature/claims
}
Is there no way to validate with just the public key?
On this line:
Algorithm algorithm = Algorithm.RSA256(publicKey, privateKey);
pass the privateKey as null. Private keys are for signing.
Algorithm algorithm = Algorithm.RSA256(publicKey, null);

Objective C: Exporting Private and Public Key from Keychain

I am able to create a public-private keypair using SecKeyGeneratePair [Apple CryptoExercise]function.
Q1. The keys in the keychain appear as without displaying any name. How can we add a friendly name to the keys.
Q2. However how can i export public and private key that has been generated in the usable format:
-----BEGIN RSA PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqCWtYiGnhAv...
-----END RSA PUBLIC KEY-----
and:
-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----
Note that they can be manually exported from the keychain but how can this be achieved using objective C Apis.
Any help would be appreciable.
There is a similar question here but without any answer: iPhone: How do you export a SecKeyRef or an NSData containing public key bits to the PEM format?
There is no need of using OpenSSL just for this purpose.
Maybe you could refer to these documents from Apple:
Obtaining a SecKeyRef Object for Public Key Cryptography and
Certificate, Key, and Trust Services Programmer’s Guide
Obtaining a SecKeyRef Object for Public Key Cryptography
Extracting Keys from the Keychain If you are using existing public and
private keys from your keychain, read Certificate, Key, and Trust
Services Programming Guide to learn how to retrieve a
SecKeychainItemRef object for that key.
Once you have obtained a SecKeychainItemRef, you can cast it to a
SecKeyRef for use with this API.
Importing Existing Public and Private Keys Importing and exporting
public and private key pairs is somewhat more complicated than
generating new keys because of the number of different key formats in
common use.
This example describes how to import and export a key pair in PEM
(Privacy Enhanced Mail) format.
To export keys to a CFDataRef object
Create and populate the key usage array.
Create and populate the key attributes array.
Set the key usage and attributes fields in the parameters object.
Set the external format and flag values appropriately.
Export the key with API as follows.
OSStatus oserr = SecItemExport(publickey,
externalFormat, // See SecExternalFormat for details
flags, // See SecItemImportExportFlags for details
&params,
(CFDataRef *)&pkdata); if (oserr) {
fprintf(stderr, "SecItemExport failed (oserr=%d)\n", oserr);
exit(-1); }
Q1. How can we add a friendly name to the keys?
Use kSecAttrLabel key to pass label in parameters dictionary of SecKeyGeneratePair().
Q2. How to export keys to PEM format?
PEM format is the same data as the DER-encoded file but it is encoded in base64 with additional header and footer lines. Data in DER format can received using kSecFormatX509Cert parameter and kSecItemPemArmour flag when calling SecItemExport().
CFTypeRef key = NULL; // your key
CFDataRef data;
SecItemExport(key, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data);
NSString* base64EncodedString = [(__bridge NSData*)data base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
NSString* pemString = [NSString stringWithFormat:#"-----BEGIN FOO BAR KEY-----\n%#\n-----END FOO BAR KEY-----", base64EncodedString];
NSData* pemData = [pemString dataUsingEncoding:NSUTF8StringEncoding];

Windows 8 Metro RSA Encryption: AsymmetricKeyAlgorithmProvider ImportPublicKey Fails

I am attempting to pass some encrypted data between a Win 8 Metro app and a RESTful WCF service. Initially the Metro app requests a public key and the WCF service returns it as a raw Stream as to avoid any pesky formatting issues. The Base 64 encoded public key is decoded in the metro app into a byte array. Here is where the problem occurs. When I attempted to call AsymmetricKeyAlgorithmProvider.ImportPublicKey I get the error "ASN1 bad tag value met".
I am using RSA PKCS1 for the encryption. Here is the relevant code:
WCF Service
string keyName = "This is passed in via a parameter";
var key = !CngKey.Exists(keyName) ? CngKey.Create(CngAlgorithm2.Rsa, keyName) : CngKey.Open(keyName);
// Create the RSA container to get keys and then dispose
using (var rsaCng = new RSACng(key) { EncryptionPaddingMode = AsymmetricPaddingMode.Pkcs1, KeySize = 2048 })
{
byte[] publicBlob = rsaCng.Key.Export(CngKeyBlobFormat.GenericPublicBlob);
publicKey = Convert.ToBase64String(publicBlob);
}
Metro App
public static string Encrypt(IBuffer dataBuffer, string publicKeyString)
{
var asymmAlg = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaPkcs1);
// The next line fails with ASN1 bad tag value met
var publicKey = asymmAlg.ImportPublicKey(CryptographicBuffer.DecodeFromBase64String(publicKeyString), CryptographicPublicKeyBlobType.Pkcs1RsaPublicKey);
var encryptedData = CryptographicEngine.Encrypt(publicKey, dataBuffer, null);
return CryptographicBuffer.EncodeToBase64String(encryptedData);
}
EDIT 1: More information below
Exporting the public key from a 2048bit key pair from the WCF service yields a 283 bit length key blob, while exporting the same type of public key from the Metro app is only 270 bits. When I import the Metro generated public key it succeeds. Any idea why the WCF service has 13 extra bits on its public key? I think those extra 13 bits are causing the failure.
Here is the Metro code that yields the shorter public key blob:
var provider = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaPkcs1);
CryptographicKey standardKeyPair = provider.CreateKeyPair(2048);
byte[] standardKey = standardKeyPair.ExportPublicKey(CryptographicPublicKeyBlobType.Pkcs1RsaPublicKey).ToArray();
Quite late, but maybe it will help you or saves someone's time...
Change the type of blob type during import. It's really wierd, but I had success with it, after experimenting.
Your code in WCF may stay as it is.
Change just the Metro code:
public static string Encrypt(IBuffer dataBuffer, string publicKeyString)
{
var asymmAlg = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaPkcs1);
// The next line fails with ASN1 bad tag value met
var publicKey = asymmAlg.ImportPublicKey(CryptographicBuffer.DecodeFromBase64String(publicKeyString), CryptographicPublicKeyBlobType.BCryptPublicKey);
var encryptedData = CryptographicEngine.Encrypt(publicKey, dataBuffer, null);
return CryptographicBuffer.EncodeToBase64String(encryptedData);
}
So the only change here is the BCryptPublicKey during the importing. Then it works. But do not ask me why :-).

How to generate a CMS (cryptographic message syntax) with Mono Framework and BouncyCastle API?

I have a Certificate in PKCS#12 format and I need to generate a CMS signature (Cryptographic Message Syntax). Due that "Mono Framework" does not have a full implemented "System.Security.Cryptography" assembly, I am trying to use "Bouncy Castle API for C#".
So, using "Bouncy Castle", I need to write an alternative code to the one I had wrote on DOTNET.
The code on DOT NET is the following:
X509Certificate2 crt = new X509Certificate2();
byte[] crtBytes = [ certificate in the format PKCS12 (certificate + private key) obtained using FileStream class]
crt.Import(crtBytes, "123456", X509KeyStorageFlags.DefaultKeySet);
Encoding msgCodificado = Encoding.UTF8;
byte[] msgBytes = msgCodificado.GetBytes(xmlTRA.OuterXml); // xmlTRA.OuterXml is the data to sign
ContentInfo pkcsContentInfo = new ContentInfo(msgBytes);
SignedCms cms = new SignedCms(pkcsContentInfo);
CmsSigner firmante = new CmsSigner(crt);
firmante.IncludeOption = X509IncludeOption.EndCertOnly;
cms.ComputeSignature(firmante); // ---> throw an cryptografy exception with MONO
byte[] firma = cms.Encode();
firmaB64 = Convert.ToBase64String(firma);
Anyone knows how to write an alternative code using "Bouncy Castle API for C#"?
Org.BouncyCastle.Pkcs has classes for working with a PKCS#12 store.
Org.BouncyCastle.Cms has classes for working with CMS messages.
There are corresponding test classes in the source code that show the basics of using, e.g. Pkcs12Store(Builder) and CmsSignedData(Generator).