Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ internal static RSAParameters ExportRsaParameters(SafeRsaHandle key, bool includ

SafeBignumHandle n, e, d, p, dmp1, q, dmq1, iqmp;
if (!GetRsaParameters(key,
includePrivateParameters ? 1 : 0,
out n,
out e,
out d,
Expand Down Expand Up @@ -163,6 +164,7 @@ internal static RSAParameters ExportRsaParameters(SafeRsaHandle key, bool includ
[return: MarshalAs(UnmanagedType.Bool)]
private static partial bool GetRsaParameters(
SafeRsaHandle key,
int includePrivateParameters,
out SafeBignumHandle n,
out SafeBignumHandle e,
out SafeBignumHandle d,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,42 @@ public static void Add_CertWithPrivateKey_NotSupportedAlgorithm()
Assert.Throws<PlatformNotSupportedException>(() => store.Add(cert));
}
}

[Fact]
public static void AndroidKeyStoreRsaPrivateKey_PublicExport()
{
using (X509Store store = new(StoreName.My, StoreLocation.CurrentUser))
using (X509Certificate2 cert = X509Certificate2.CreateFromPem(TestData.RsaCertificate, TestData.RsaPkcs8Key))
using (X509Certificate2 certOnly = new(cert.RawData))
{
store.Open(OpenFlags.ReadWrite);
store.Remove(certOnly);

try
{
store.Add(cert);

using (ImportedCollection coll = new ImportedCollection(store.Certificates))
{
byte[] thumbprint = certOnly.GetCertHash(HashAlgorithmName.SHA256);
X509Certificate2 storeCert = Assert.Single(
coll.Collection.FindByThumbprint(HashAlgorithmName.SHA256, thumbprint));

Assert.True(storeCert.HasPrivateKey);
Comment thread
vcsjones marked this conversation as resolved.

using RSA rsa = storeCert.GetRSAPrivateKey();
RSAParameters publicParameters = rsa.ExportParameters(false);
Assert.NotNull(publicParameters.Modulus);
Assert.NotNull(publicParameters.Exponent);

Assert.Throws<CryptographicException>(() => rsa.ExportParameters(true));
}
}
finally
{
store.Remove(certOnly);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ PALEXPORT int32_t AndroidCryptoNative_RsaGenerateKeyEx(RSA* rsa, int32_t bits)
}

PALEXPORT int32_t AndroidCryptoNative_GetRsaParameters(RSA* rsa,
int32_t includePrivateParameters,
jobject* n, jobject* e, jobject* d, jobject* p, jobject* dmp1, jobject* q, jobject* dmq1, jobject* iqmp)
{
if (!rsa || !n || !e || !d || !p || !dmp1 || !q || !dmq1 || !iqmp)
Expand Down Expand Up @@ -398,12 +399,26 @@ PALEXPORT int32_t AndroidCryptoNative_GetRsaParameters(RSA* rsa,
return FAIL;
}

*n = NULL;
*e = NULL;
*d = NULL;
*p = NULL;
*q = NULL;
*dmp1 = NULL;
*dmq1 = NULL;
*iqmp = NULL;

JNIEnv* env = GetJNIEnv();
jobject privateKey = rsa->privateKey;
jobject publicKey = rsa->publicKey;

if (privateKey)
if (includePrivateParameters)
{
if (!privateKey || !(*env)->IsInstanceOf(env, privateKey, g_RSAPrivateCrtKeyClass))
{
return FAIL;
}

*e = ToGRef(env, (*env)->CallObjectMethod(env, privateKey, g_RSAPrivateCrtKeyPubExpField));
*n = ToGRef(env, (*env)->CallObjectMethod(env, privateKey, g_RSAPrivateCrtKeyModulusField));
*d = ToGRef(env, (*env)->CallObjectMethod(env, privateKey, g_RSAPrivateCrtKeyPrivExpField));
Expand All @@ -417,12 +432,11 @@ PALEXPORT int32_t AndroidCryptoNative_GetRsaParameters(RSA* rsa,
{
*e = ToGRef(env, (*env)->CallObjectMethod(env, publicKey, g_RSAPublicKeyGetPubExpMethod));
*n = ToGRef(env, (*env)->CallObjectMethod(env, publicKey, g_RSAKeyGetModulus));
*d = NULL;
*p = NULL;
*q = NULL;
*dmp1 = NULL;
*dmq1 = NULL;
*iqmp = NULL;
}
else if (privateKey && (*env)->IsInstanceOf(env, privateKey, g_RSAPrivateCrtKeyClass))
{
*e = ToGRef(env, (*env)->CallObjectMethod(env, privateKey, g_RSAPrivateCrtKeyPubExpField));
*n = ToGRef(env, (*env)->CallObjectMethod(env, privateKey, g_RSAPrivateCrtKeyModulusField));
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ typedef enum

typedef struct RSA
{
jobject privateKey; // RSAPrivateCrtKey
jobject publicKey; // RSAPublicCrtKey
jobject privateKey; // RSAPrivateKey
jobject publicKey; // RSAPublicKey
atomic_int refCount;
int32_t keyWidthInBits;
} RSA;
Expand All @@ -36,7 +36,7 @@ PALEXPORT int32_t AndroidCryptoNative_RsaSignPrimitive(int32_t flen, uint8_t* fr
PALEXPORT int32_t AndroidCryptoNative_RsaVerificationPrimitive(int32_t flen, uint8_t* from, uint8_t* to, RSA* rsa);
PALEXPORT int32_t AndroidCryptoNative_RsaSize(RSA* rsa);
PALEXPORT int32_t AndroidCryptoNative_RsaGenerateKeyEx(RSA* rsa, int32_t bits);
PALEXPORT int32_t AndroidCryptoNative_GetRsaParameters(RSA* rsa,
PALEXPORT int32_t AndroidCryptoNative_GetRsaParameters(RSA* rsa, int32_t includePrivateParameters,
jobject* n, jobject* e, jobject* d, jobject* p, jobject* dmp1, jobject* q, jobject* dmq1, jobject* iqmp);
PALEXPORT int32_t AndroidCryptoNative_SetRsaParameters(RSA* rsa,
uint8_t* n, int32_t nLength, uint8_t* e, int32_t eLength, uint8_t* d, int32_t dLength,
Expand Down
Loading