YOUSEFUL / DELPHI / COMPONENTS

TAtlasSecretBox

Seal and open bytes or text with a 32-byte key or a password, using AES-256-GCM with generated nonces and salts.

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

Description

The class most applications should use for values that fit in memory. One call seals, one call opens; opening either returns exactly what was sealed or raises EAtlasCryptoError. Every nonce and salt is drawn from the system random generator and stored in the box, so sealing the same data twice gives different boxes.

Formats (integers big-endian):

The header is authenticated with the data, so changing the iteration count or salt breaks the tag, and every single byte of a box is protected. A Context value is authenticated but not stored: use it to tie a box to a record id or purpose so it cannot be moved elsewhere. Every failure to open raises the same message, Decryption failed: wrong key or password, or the data was altered.

These are Atlas Crypto's own formats. Another implementation can read them from the description above, but no interoperability test has been made.

Members

MemberKindWhat it does
KeySizefieldThe key length in bytes (AES-256).
MaxIterationsfieldThe most PBKDF2 rounds a password box may ask for.
NewKeymethodReturns a new random 32-byte key.
SealmethodReturns an ASB1 box of Plain under Key, 32 bytes longer than Plain.
OpenmethodReturns the sealed bytes when Key and Context are the ones used to seal and the box is unaltered.
SealWithPasswordmethodReturns an ASP1 box of Plain, 52 bytes longer than Plain, with a key derived from Password and a fresh 16-byte salt.
OpenWithPasswordmethodReturns the sealed bytes of an ASP1 box.
SealTextmethodSeals the UTF-8 encoding of Text with Password and returns the box as URL-safe base64, ready for a text column, a configuration file or a URL.
OpenTextmethodReturns the text sealed by SealText.

Methods

NewKey method

class function NewKey: TBytes; static;

Returns a new random 32-byte key. Keep it in protected storage and Wipe it after use.

pascal
Key := TAtlasSecretBox.NewKey;

Seal method

class function Seal(const Key, Plain: TBytes; const Context: TBytes = nil): TBytes; static;

Returns an ASB1 box of Plain under Key, 32 bytes longer than Plain. Plain may be empty. A key that is not 32 bytes raises EAtlasCryptoError.

pascal
Box := TAtlasSecretBox.Seal(Key, Plain, TAtlasBytes.OfString('invoice:1042'));

Open method

class function Open(const Key, Box: TBytes; const Context: TBytes = nil): TBytes; static;

Returns the sealed bytes when Key and Context are the ones used to seal and the box is unaltered. Otherwise raises EAtlasCryptoError with the single decryption message. A key that is not 32 bytes raises its own message.

pascal
Plain := TAtlasSecretBox.Open(Key, Box, TAtlasBytes.OfString('invoice:1042'));

SealWithPassword method

class function SealWithPassword(const Password: string; const Plain: TBytes; Iterations: Integer = TAtlasKdf.DefaultPasswordIterations): TBytes; static;

Returns an ASP1 box of Plain, 52 bytes longer than Plain, with a key derived from Password and a fresh 16-byte salt. An empty password, or Iterations outside 1 to 20,000,000, raises EAtlasCryptoError. Lower counts are for tests only.

pascal
Box := TAtlasSecretBox.SealWithPassword(Password, Plain);

OpenWithPassword method

class function OpenWithPassword(const Password: string; const Box: TBytes): TBytes; static;

Returns the sealed bytes of an ASP1 box. The iteration count and salt come from the box. Passwords are case sensitive. Any failure raises the single decryption message.

pascal
Plain := TAtlasSecretBox.OpenWithPassword(Password, Box);

SealText method

class function SealText(const Password, Text: string; Iterations: Integer = TAtlasKdf.DefaultPasswordIterations): string; static;

Seals the UTF-8 encoding of Text with Password and returns the box as URL-safe base64, ready for a text column, a configuration file or a URL. Password first, text second.

pascal
Sealed := TAtlasSecretBox.SealText(Password, 'my note');

OpenText method

class function OpenText(const Password, Sealed: string): string; static;

Returns the text sealed by SealText. White space before and after Sealed is ignored; text that is not URL-safe base64 fails like any other bad box.

pascal
Text := TAtlasSecretBox.OpenText(Password, Sealed);

Fields

KeySize field

const KeySize = 32;

The key length in bytes (AES-256). Seal, Open and the key functions of TAtlasStreamCrypt refuse other lengths.

MaxIterations field

const MaxIterations = 20000000;

The most PBKDF2 rounds a password box may ask for. Opening refuses a larger count, read from the untrusted header, before doing any work, so a forged box cannot tie up the process; sealing refuses it too.

Examples

Seal with a key and a context, then with a password

Prints 42 (10 bytes plus 32), TRUE, record 7 moved: refused, and pin 4712.

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

procedure BoxesTwoWays;
var
  Key, Box: TBytes;
  Sealed: string;
begin
  Key := TAtlasSecretBox.NewKey;
  Box := TAtlasSecretBox.Seal(Key, TAtlasBytes.OfString('0123456789'), TAtlasBytes.OfString('record 7'));
  WriteLn(Length(Box));
  WriteLn(TEncoding.UTF8.GetString(TAtlasSecretBox.Open(Key, Box, TAtlasBytes.OfString('record 7'))) = '0123456789');
  try
    TAtlasSecretBox.Open(Key, Box, TAtlasBytes.OfString('record 8'));
  except
    on EAtlasCryptoError do WriteLn('record 7 moved: refused');
  end;
  TAtlasBytes.Wipe(Key);
  Sealed := TAtlasSecretBox.SealText('a long pass phrase', 'pin 4712');
  WriteLn(TAtlasSecretBox.OpenText('a long pass phrase', Sealed));
end;

TAtlasStreamCrypt · TAtlasFileProtector · TAtlasAesGcm · TAtlasKdf · EAtlasCryptoError

Also in Atlas Crypto

TAtlasHashCalculator · TAtlasFileProtector