Class ReencryptResult

java.lang.Object
co.ankatech.ankasecure.sdk.model.ReencryptResult

public final class ReencryptResult extends Object
Result of a re-encryption operation.

Contains the new JWE token produced by server-side re-encryption from one key to another, along with comprehensive metadata for both the old decryption key and the new encryption key. The plaintext is never exposed to the client during this operation.

Use Cases

  • Key rotation for encrypted data without client-side decryption
  • Migrating encrypted data to stronger algorithms
  • Compliance-driven periodic key rotation
  • Transparent key migration for legacy encrypted files

JWE Token Structure

When the new key is a single-recipient key, getJweToken() returns a Compact JWE (RFC 7516 §7.1) containing five Base64URL segments; when it is a composite KEM key, the token is the §7.2 General JSON JWE carrying one recipient per component, which Compact Serialization cannot hold. The Compact form is:


 BASE64URL(ProtectedHeader).
 BASE64URL(EncryptedKey).
 BASE64URL(IV).
 BASE64URL(Ciphertext).
 BASE64URL(AuthenticationTag)
 

Every recipient of the produced JWE

getRecipients() lists every recipient of the re-encrypted JWE, in its order: the key each one names, the key-material version its content-encryption key was wrapped to, and that key's algorithm. For a JWE addressed to several keys, the one named by sourceKid is replaced by the new key at its position and every other recipient is kept, re-wrapped at its current PRIMARY.


 ReencryptResult result = sdk.reencrypt("archive-2026", "custodian-a", multiRecipientJwe);
 for (ReencryptedRecipient r : result.getRecipients()) {
     System.out.println(r.getKid() + " (" + r.getAlgorithm() + ") v" + r.getMaterialVersion());
 }
 

Migration Mode

The isMigrationMode() flag indicates whether the operation handled legacy ciphertext without a kid in the header. This is useful for auditing and tracking migration workflows.

Thread Safety

Instances are effectively immutable after construction. All setters are for internal SDK use during deserialization. Once returned from SDK methods, instances are safe to share across threads.

Example


 // Re-encrypt from old key to new key
 ReencryptResult result = sdk.reencrypt("new-ml-kem-key", oldJweToken);

 System.out.println("Re-encryption complete");
 System.out.println("Old key: " + result.getOldKeyRequested() +
                    " (" + result.getOldKeyAlgorithmUsed() + ")");
 System.out.println("New key: " + result.getNewKeyRequested() +
                    " (" + result.getNewKeyAlgorithmUsed() + ")");
 System.out.println("Material versions: " + result.getSourceMaterialVersion() +
                    " -> " + result.getTargetMaterialVersion());

 if (result.isMigrationMode()) {
     System.out.println("Migrated legacy ciphertext to managed format");
 }

 // New JWE token ready for storage
 String newJwe = result.getJweToken();
 
See Also:
  • Constructor Details

    • ReencryptResult

      public ReencryptResult()
  • Method Details

    • getJweToken

      public String getJweToken()
      Returns the new JWE token after re-encryption.

      The token contains the same plaintext as the original JWE but encrypted with the new key. It is self-contained and can be stored or transmitted independently.

      Server-supplied and unrendered: display it through InertText.text(String).

      Returns:
      the Compact JWE string (five Base64URL segments), or the General JSON JWE string when the new key is a composite KEM key; never null
    • getOldKeyRequested

      public String getOldKeyRequested()
      Returns the original key identifier requested for decryption.

      Server-supplied and unrendered: display it through InertText.text(String).

      Returns:
      non-null old kid
    • getSourceMaterialVersion

      public Integer getSourceMaterialVersion()
      Returns the key-material version that decrypted the original payload under the source Stable KID.
      Returns:
      source material version; null when not resolvable — never 0
    • getOldKeyAlgorithmUsed

      public String getOldKeyAlgorithmUsed()
      Returns the hybrid algorithm used for decryption.

      Server-supplied and unrendered: display it through InertText.text(String).

      Returns:
      non-null algorithm identifier
    • getNewKeyRequested

      public String getNewKeyRequested()
      Returns the original key identifier requested for encryption.

      Server-supplied and unrendered: display it through InertText.text(String).

      Returns:
      non-null new kid
    • getTargetMaterialVersion

      public Integer getTargetMaterialVersion()
      Returns the PRIMARY key-material version that encrypted the new payload under the target Stable KID.
      Returns:
      target material version; null when not resolvable — never 0
    • getNewKeyAlgorithmUsed

      public String getNewKeyAlgorithmUsed()
      Returns the hybrid algorithm used for encryption.

      Server-supplied and unrendered: display it through InertText.text(String).

      Returns:
      non-null algorithm identifier
    • getRecipients

      public List<co.ankatech.secure.client.model.ReencryptedRecipient> getRecipients()
      Returns every recipient of the re-encrypted JWE, in the JWE's recipient order: the key each one names (kid), the key-material version its content-encryption key was wrapped to (materialVersion), and that key's catalogue algorithm (algorithm).

      A single-recipient JWE lists its one recipient. For a JWE addressed to several keys the new key sits at the position of the replaced recipient and every other recipient is listed with the version it was re-wrapped at.

      Example:

      
       ReencryptResult result = sdk.reencryptFileCompact("archive-2026", "custodian-a",
               Path.of("board-minutes.jwe"), Path.of("board-minutes.rotated.jwe"));
       result.getRecipients().forEach(r -> log.info("recipient {} v{}", r.getKid(), r.getMaterialVersion()));
       
      Returns:
      the recipients of the produced JWE, unmodifiable, and each call returns fresh copies of the entries, so changing one changes nothing in this result; null on the streaming path, whose response carries no recipient list
    • getWarnings

      public List<CryptoWarning> getWarnings()
      Returns non-fatal warnings encountered during the re-encryption operation.

      Warnings are type-safe instances that may relate to either the old decryption key or the new encryption key. Use pattern matching for programmatic handling:

      
       ReencryptResult result = sdk.reencrypt("new-key", oldJweToken);
      
       if (result.getWarnings() != null && !result.getWarnings().isEmpty()) {
           for (CryptoWarning warning : result.getWarnings()) {
               switch (warning) {
                   case KeyExpirationWarning kew -> {
                       logger.warn("Key expiring in {} days - Old: {}, New: {}",
                           kew.daysRemaining(),
                           result.getOldKeyRequested(),
                           result.getNewKeyRequested());
                       if (kew.severity() == WarningSeverity.CRITICAL) {
                           alertOps("Urgent key rotation needed");
                       }
                   }
                   case UsageLimitWarning ulw ->
                       logger.warn("{} - {}", ulw.message(), ulw.recommendedAction());
                   case GenericWarning gw when gw.rawMessage().contains("MIGRATION_MODE") ->
                       auditLog("Migrated legacy ciphertext to managed format");
                   case GenericWarning gw ->
                       logger.info("Warning: {}", gw.rawMessage());
               }
           }
       }
       

      Common warning types:

      Returns:
      unmodifiable list of warnings (null if no warnings, never empty if non-null)
    • isMigrationMode

      public boolean isMigrationMode()
      Indicates whether the operation ran in migration mode.

      Returns true if the original ciphertext lacked a kid in the JWE header and a sourceKid was provided to name the key it was produced for. This is typical for legacy encrypted files.

      Returns:
      true if migration mode was used; false for normal managed re-encryption