YOUSEFUL / DELPHI / COMPONENTS

TAtlasRsa

RSA with OAEP (SHA-256) encryption of short secrets and PSS (SHA-256, 32-byte salt) signatures, for keys of 2048 to 8192 bits.

Class Unit Atlas.CryptoKeys · Inherits TObject · Product Atlas Crypto

Description

RSA encryption only takes short messages: at most the modulus size minus 66 bytes (190 bytes for 2048 bits, 318 for 3072). Use it to wrap a random content key, and seal the data itself with TAtlasSecretBox. OAEP and PSS are both randomised, so the same input gives different ciphertexts and signatures. Ciphertexts and signatures are as long as the modulus.

PKCS#1 v1.5 encryption, raw RSA, SHA-1 and keys below 2048 bits are not offered. Generating an RSA key pair is much slower than an elliptic-curve pair, and the time varies because it searches for random primes (one 3072-bit pair took about half a second on the machine used to write this page), so generate once and store it. Decrypt fails with one message whatever went wrong inside. Verify returns False for any mismatch and raises only when the public key cannot be imported. RSA is covered by round-trip tests only; there is no interoperability test against another library.

Members

MemberKindWhat it does
GenerateKeyPairmethodReturns a new key pair of Bits bits: 2048 to 8192, in steps of 64; anything else raises EAtlasCryptoError.
EncryptmethodEncrypts Plain with RSA-OAEP (SHA-256, no label) and returns a ciphertext as long as the modulus.
DecryptmethodReturns the plaintext, or raises EAtlasCryptoError (Decryption failed: wrong key, or the data was altered) for an altered ciphertext or the wrong key, without revealing which check failed.
SignmethodReturns an RSA-PSS signature (SHA-256 digest of Data, 32-byte salt), as long as the modulus.
VerifymethodTrue when Signature is a valid PSS signature of Data for PublicKey.
KeyBitsmethodReturns the modulus size in bits read from the header of an RSA public or private blob.

Methods

GenerateKeyPair method

class function GenerateKeyPair(Bits: Integer = 3072): TAtlasKeyPair; static;

Returns a new key pair of Bits bits: 2048 to 8192, in steps of 64; anything else raises EAtlasCryptoError. The default 3072 bits matches the strength of P-256.

pascal
Pair := TAtlasRsa.GenerateKeyPair(2048);

Encrypt method

class function Encrypt(const PublicKey, Plain: TBytes): TBytes; static;

Encrypts Plain with RSA-OAEP (SHA-256, no label) and returns a ciphertext as long as the modulus. A message longer than the limit raises EAtlasCryptoError (Encrypting with RSA (is the message longer than the key allows?) failed ...).

pascal
Wrapped := TAtlasRsa.Encrypt(Pair.PublicKey, Key);

Decrypt method

class function Decrypt(const PrivateKey, Cipher: TBytes): TBytes; static;

Returns the plaintext, or raises EAtlasCryptoError (Decryption failed: wrong key, or the data was altered) for an altered ciphertext or the wrong key, without revealing which check failed. A public key blob in place of the private key raises a key import error.

pascal
Key := TAtlasRsa.Decrypt(Pair.PrivateKey, Wrapped);

Sign method

class function Sign(const PrivateKey, Data: TBytes): TBytes; static;

Returns an RSA-PSS signature (SHA-256 digest of Data, 32-byte salt), as long as the modulus.

pascal
Signature := TAtlasRsa.Sign(Pair.PrivateKey, Data);

Verify method

class function Verify(const PublicKey, Data, Signature: TBytes): Boolean; static;

True when Signature is a valid PSS signature of Data for PublicKey. False for any mismatch, including an empty or wrong-length signature. Raises EAtlasCryptoError when PublicKey cannot be imported as an RSA public key.

pascal
Valid := TAtlasRsa.Verify(Pair.PublicKey, Data, Signature);

KeyBits method

class function KeyBits(const Key: TBytes): Integer; static;

Returns the modulus size in bits read from the header of an RSA public or private blob. It only checks that the blob has at least 8 bytes (otherwise EAtlasCryptoError); it does not check that the blob is an RSA key, so pass only keys from GenerateKeyPair.

pascal
Bits := TAtlasRsa.KeyBits(Pair.PublicKey);

Examples

Wrap a content key and sign a release note

Prints 2048, TRUE for the unwrapped key and TRUE for the signature.

pascal
uses System.SysUtils, Atlas.Crypto, Atlas.CryptoBox, Atlas.CryptoKeys;

procedure RsaWrapAndSign;
var
  Pair: TAtlasKeyPair;
  ContentKey, Wrapped, Signature: TBytes;
begin
  Pair := TAtlasRsa.GenerateKeyPair(2048);
  try
    WriteLn(TAtlasRsa.KeyBits(Pair.PublicKey));
    ContentKey := TAtlasSecretBox.NewKey;
    Wrapped := TAtlasRsa.Encrypt(Pair.PublicKey, ContentKey);
    WriteLn(TAtlasBytes.ConstantTimeEquals(TAtlasRsa.Decrypt(Pair.PrivateKey, Wrapped), ContentKey));
    Signature := TAtlasRsa.Sign(Pair.PrivateKey, TAtlasBytes.OfString('release 4.2'));
    WriteLn(TAtlasRsa.Verify(Pair.PublicKey, TAtlasBytes.OfString('release 4.2'), Signature));
  finally
    Pair.Wipe;
    TAtlasBytes.Wipe(ContentKey);
  end;
end;

TAtlasKeyPair · TAtlasSecretBox · TAtlasEcdsa

Also in Atlas Crypto

TAtlasHashCalculator · TAtlasFileProtector