All Implemented Interfaces:
Component, DestructableComponent, InitializableComponent

public class DataSealer extends AbstractInitializableComponent
Applies a MAC to time-limited information and encrypts with a symmetric key. TODO: make final
  • Field Details

    • MAGIC_STRING

      @Nonnull @NotEmpty public static final String MAGIC_STRING
      Magic string to signal use of per-node prefix feature.
      See Also:
    • PREFIX_LEN

      private static final int PREFIX_LEN
      Length of padded prefix.
      See Also:
    • CHUNK_SIZE

      private static final int CHUNK_SIZE
      Size of UTF-8 data chunks to read/write.
      See Also:
    • log

      @Nonnull private org.slf4j.Logger log
      Class logger.
    • lockedAtStartup

      private boolean lockedAtStartup
      Whether the key source is expected to be locked initially.
    • keyStrategy

      Source of keys.
    • random

      Source of secure random data.
    • encoder

      @Nonnull private org.apache.commons.codec.BinaryEncoder encoder
      Encodes encrypted bytes to string.
    • decoder

      @Nonnull private org.apache.commons.codec.BinaryDecoder decoder
      Decodes encrypted string to bytes.
    • nodePrefix

      @Nullable private String nodePrefix
      Optional per-server node prefix to affix to encoded values.
  • Constructor Details

    • DataSealer

      public DataSealer()
      Constructor.
  • Method Details

    • setLockedAtStartup

      public void setLockedAtStartup(boolean flag)
      Set whether the key source is expected to be locked at startup, and unlocked later at runtime.

      Defaults to false.

      Parameters:
      flag - flag to set
      Since:
      7.4.0
    • setKeyStrategy

      public void setKeyStrategy(@Nonnull DataSealerKeyStrategy strategy)
      Set the key strategy.
      Parameters:
      strategy - key strategy
    • setRandom

      public void setRandom(@Nonnull SecureRandom r)
      Set the pseudorandom generator.
      Parameters:
      r - the pseudorandom generator to set
    • setEncoder

      public void setEncoder(@Nonnull org.apache.commons.codec.BinaryEncoder e)
      Sets the encoder to use to produce a ciphertext string from bytes. Default is standard base-64 encoding without line breaks.
      Parameters:
      e - Byte-to-string encoder.
    • setDecoder

      public void setDecoder(@Nonnull org.apache.commons.codec.BinaryDecoder d)
      Sets the decoder to use to convert a ciphertext string to bytes. Default is standard base-64 decoding.
      Parameters:
      d - String-to-byte decoder.
    • setNodePrefix

      public void setNodePrefix(@Nullable @NotEmpty String prefix)
      Set a prefix to affix to wrapped values to support signaling to load balancers, etc.

      The prefix will itself be prefixed by MAGIC_STRING for compatibility with unprefixed values.

      Parameters:
      prefix - node prefix
      Since:
      8.3.0
    • doInitialize

      public void doInitialize() throws ComponentInitializationException
      Performs the initialization of the component. This method is executed within the lock on the object being initialized. The default implementation of this method is a no-op.
      Overrides:
      doInitialize in class AbstractInitializableComponent
      Throws:
      ComponentInitializationException - thrown if there is a problem initializing the component
    • unwrap

      @Nonnull public String unwrap(@Nonnull @NotEmpty String wrapped) throws DataSealerException
      Decrypts and verifies an encrypted bundle created with wrap(String, Instant).
      Parameters:
      wrapped - the encoded blob
      Returns:
      the decrypted data, if it's unexpired
      Throws:
      DataSealerException - if the data cannot be unwrapped and verified
    • unwrap

      @Nonnull public String unwrap(@Nonnull @NotEmpty String wrapped, @Nullable StringBuffer keyUsed) throws DataSealerException
      Decrypts and verifies an encrypted bundle created with wrap(String, Instant), optionally returning the label of the key used to encrypt the data.
      Parameters:
      wrapped - the encoded blob
      keyUsed - a buffer to receive the alias of the key used to encrypt the data
      Returns:
      the decrypted data, if it's unexpired
      Throws:
      DataSealerException - if the data cannot be unwrapped and verified
    • extractAndCheckDecryptedData

      @Nonnull private String extractAndCheckDecryptedData(@Nonnull @NotEmpty byte[] decryptedBytes) throws DataSealerException
      Extract the GZIP'd data and test for expiration before returning it.
      Parameters:
      decryptedBytes - the data we are looking at
      Returns:
      the decoded data if it is valid and unexpired
      Throws:
      DataSealerException - if the data cannot be unwrapped and verified
    • wrap

      @Nonnull public String wrap(@Nonnull @NotEmpty String data) throws DataSealerException
      Equivalent to wrap(String, Instant) with expiration set to "never".
      Parameters:
      data - the data to wrap
      Returns:
      the encoded blob
      Throws:
      DataSealerException - if the wrapping operation fails
    • wrap

      @Nonnull public String wrap(@Nonnull @NotEmpty String data, @Nullable Instant exp) throws DataSealerException
      Encodes data into an AEAD-encrypted blob, gzip(exp|data)
      • exp = expiration time of the data; 8 bytes; Big-endian
      • data = the data; a UTF-8-encoded string

      As part of encryption, the key alias is supplied as additional authenticated data to the cipher. Afterwards, the encrypted data is prepended by the IV and then again by the alias (in length-prefixed UTF-8 format), which identifies the key used. Finally the result is base64-encoded.

      Parameters:
      data - the data to wrap
      exp - expiration time or null for none
      Returns:
      the encoded blob
      Throws:
      DataSealerException - if the wrapping operation fails
    • testEncryption

      private void testEncryption(@Nullable SecretKey key) throws DataSealerException
      Run a test over the configured bean properties.
      Parameters:
      key - key to test
      Throws:
      DataSealerException - if the test fails