Skip to content

Commit

Permalink
Pkcs11RsaProvider supports encryption and decryption with Pkcs1 padding
Browse files Browse the repository at this point in the history
This is corrected implementation of #32
  • Loading branch information
jariq committed Apr 21, 2024
1 parent 72d59b2 commit 8b32c33
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 4 deletions.
58 changes: 54 additions & 4 deletions src/Pkcs11Interop.X509Store.Tests/Pkcs11RsaProviderTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public class Pkcs11RsaProviderTest
private byte[] _data2 = Encoding.UTF8.GetBytes("Hola mundo!");

[Test]
public void RsaPkcs1SelfTest()
public void RsaSigningPkcs1SelfTest()
{
using (var store = new Pkcs11X509Store(SoftHsm2Manager.LibraryPath, SoftHsm2Manager.PinProvider))
{
Expand Down Expand Up @@ -66,7 +66,7 @@ public void RsaPkcs1SelfTest()
}

[Test]
public void RsaPkcs1PlatformTest()
public void RsaSigningPkcs1PlatformTest()
{
using (var store = new Pkcs11X509Store(SoftHsm2Manager.LibraryPath, SoftHsm2Manager.PinProvider))
{
Expand Down Expand Up @@ -102,7 +102,7 @@ public void RsaPkcs1PlatformTest()
}

[Test]
public void RsaPssSelfTest()
public void RsaSigningPssSelfTest()
{
using (var store = new Pkcs11X509Store(SoftHsm2Manager.LibraryPath, SoftHsm2Manager.PinProvider))
{
Expand Down Expand Up @@ -133,7 +133,7 @@ public void RsaPssSelfTest()
}

[Test]
public void RsaPssPlatformTest()
public void RsaSigningPssPlatformTest()
{
using (var store = new Pkcs11X509Store(SoftHsm2Manager.LibraryPath, SoftHsm2Manager.PinProvider))
{
Expand Down Expand Up @@ -167,5 +167,55 @@ public void RsaPssPlatformTest()
}
}
}

[Test]
public void RsaEncryptionPkcs1SelfTest()
{
using (var store = new Pkcs11X509Store(SoftHsm2Manager.LibraryPath, SoftHsm2Manager.PinProvider))
{
Pkcs11X509Certificate cert = Helpers.GetCertificate(store, SoftHsm2Manager.Token1Label, SoftHsm2Manager.Token1TestUserRsaLabel);

RSA p11PrivKey = cert.GetRSAPrivateKey();
ClassicAssert.IsNotNull(p11PrivKey);
RSA p11PubKey = cert.GetRSAPublicKey();
ClassicAssert.IsNotNull(p11PubKey);

byte[] encData = p11PubKey.Encrypt(_data1, RSAEncryptionPadding.Pkcs1);
ClassicAssert.IsNotNull(encData);

byte[] decData = p11PrivKey.Decrypt(encData, RSAEncryptionPadding.Pkcs1);
ClassicAssert.IsNotNull(decData);

CollectionAssert.AreEqual(decData, _data1);
}
}

[Test]
public void RsaEncryptionPkcs1PlatformTest()
{
using (var store = new Pkcs11X509Store(SoftHsm2Manager.LibraryPath, SoftHsm2Manager.PinProvider))
{
Pkcs11X509Certificate cert = Helpers.GetCertificate(store, SoftHsm2Manager.Token1Label, SoftHsm2Manager.Token1TestUserRsaLabel);

RSA p11PrivKey = cert.GetRSAPrivateKey();
ClassicAssert.IsNotNull(p11PrivKey);
RSA p11PubKey = cert.GetRSAPublicKey();
ClassicAssert.IsNotNull(p11PubKey);
RSA cngKey = CryptoObjects.GetTestUserPlatformRsaProvider();
ClassicAssert.IsNotNull(cngKey);

byte[] encData1 = p11PubKey.Encrypt(_data1, RSAEncryptionPadding.Pkcs1);
ClassicAssert.IsNotNull(encData1);
byte[] decData1 = cngKey.Decrypt(encData1, RSAEncryptionPadding.Pkcs1);
ClassicAssert.IsNotNull(decData1);
CollectionAssert.AreEqual(decData1, _data1);

byte[] encData2 = cngKey.Encrypt(_data2, RSAEncryptionPadding.Pkcs1);
ClassicAssert.IsNotNull(encData2);
byte[] decData2 = p11PrivKey.Decrypt(encData2, RSAEncryptionPadding.Pkcs1);
ClassicAssert.IsNotNull(decData2);
CollectionAssert.AreEqual(decData2, _data2);
}
}
}
}
59 changes: 59 additions & 0 deletions src/Pkcs11Interop.X509Store/Pkcs11RsaProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,65 @@ public override bool VerifyHash(byte[] hash, byte[] signature, HashAlgorithmName
}
}

/// <summary>
/// Decrypts the input data using the specified padding mode
/// </summary>
/// <param name="data">The data to decrypt</param>
/// <param name="padding">The padding mode</param>
/// <returns>The decrypted data</returns>
public override byte[] Decrypt(byte[] data, RSAEncryptionPadding padding)
{
if (data == null || data.Length == 0)
throw new ArgumentNullException(nameof(data));

if (padding == null)
throw new ArgumentNullException(nameof(padding));

if (padding == RSAEncryptionPadding.Pkcs1)
{
using (ISession session = _certContext.TokenContext.SlotContext.Slot.OpenSession(SessionType.ReadOnly))
using (IMechanism mechanism = session.Factories.MechanismFactory.Create(CKM.CKM_RSA_PKCS))
{
if (_certContext.KeyUsageRequiresLogin)
throw new NotSupportedException("Decryption with key that requires context specific login to be perfromed is not supported");
else
return session.Decrypt(mechanism, _certContext.PrivKeyHandle, data);
}
}
else
{
throw new NotSupportedException(string.Format("Padding {0} is not supported", padding));
}
}

/// <summary>
/// Encrypts the input data using the specified padding mode
/// </summary>
/// <param name="data">The data to encrypt</param>
/// <param name="padding">The padding mode</param>
/// <returns>The encrypted data</returns>
public override byte[] Encrypt(byte[] data, RSAEncryptionPadding padding)
{
if (data == null || data.Length == 0)
throw new ArgumentNullException(nameof(data));

if (padding == null)
throw new ArgumentNullException(nameof(padding));

if (padding == RSAEncryptionPadding.Pkcs1)
{
using (ISession session = _certContext.TokenContext.SlotContext.Slot.OpenSession(SessionType.ReadOnly))
using (IMechanism mechanism = session.Factories.MechanismFactory.Create(CKM.CKM_RSA_PKCS))
{
return session.Encrypt(mechanism, _certContext.PubKeyHandle, data);
}
}
else
{
throw new NotSupportedException(string.Format("Padding {0} is not supported", padding));
}
}

/// <summary>
/// Decrypts the input data using the private key
/// </summary>
Expand Down

0 comments on commit 8b32c33

Please sign in to comment.