[java-shib-shared] branch main updated: JSSH-80 - Add API to DataSealer for unwrapping expired data

Codeberg noreply at shibboleth.net
Wed Jul 29 18:44:33 UTC 2026


This is an automated email from the git hooks/post-receive script.

codeberg pushed a commit to branch main
in repository java-shib-shared.

View the commit online:
https://codeberg.org/Shibboleth/java-shib-shared/commit/93d9362480c134eaef9a0c146efa76966a8151b2

The following commit(s) were added to refs/heads/main by this push:
     new 93d93624 JSSH-80 - Add API to DataSealer for unwrapping expired data
93d93624 is described below

commit 93d9362480c134eaef9a0c146efa76966a8151b2
Author: Scott Cantor <scott at restingparrotsoftware.com>
AuthorDate: Wed Jul 29 14:22:30 2026 -0400

    JSSH-80 - Add API to DataSealer for unwrapping expired data
    
    https://shibboleth.atlassian.net/browse/JSSH-80
    
    Capture data expiration in exception.
---
 .../shared/security/DataExpiredException.java      | 76 ++++++++++++++++++++--
 .../net/shibboleth/shared/security/DataSealer.java | 13 +++-
 2 files changed, 82 insertions(+), 7 deletions(-)

diff --git a/shib-security/src/main/java/net/shibboleth/shared/security/DataExpiredException.java b/shib-security/src/main/java/net/shibboleth/shared/security/DataExpiredException.java
index e3cc9754..75b142f7 100644
--- a/shib-security/src/main/java/net/shibboleth/shared/security/DataExpiredException.java
+++ b/shib-security/src/main/java/net/shibboleth/shared/security/DataExpiredException.java
@@ -14,9 +14,13 @@
 
 package net.shibboleth.shared.security;
 
+import java.time.Instant;
+
 import javax.annotation.Nullable;
 
-/** Indicates the sealed data has expired. */
+/**
+ * Indicates the sealed data has expired.
+ */
 public class DataExpiredException extends DataSealerException {
 
     /**
@@ -24,10 +28,14 @@ public class DataExpiredException extends DataSealerException {
      */
     private static final long serialVersionUID = -4345061831894801408L;
 
+    /** Expiration. */
+    @Nullable private final Instant expiration;
+    
     /**
      * Constructor.
      */
     public DataExpiredException() {
+        this((Instant) null);
     }
 
     /**
@@ -36,7 +44,7 @@ public class DataExpiredException extends DataSealerException {
      * @param message exception message
      */
     public DataExpiredException(@Nullable final String message) {
-        super(message);
+        this(message, (Instant) null);
     }
 
     /**
@@ -45,7 +53,7 @@ public class DataExpiredException extends DataSealerException {
      * @param wrappedException exception to be wrapped by this one
      */
     public DataExpiredException(@Nullable final Exception wrappedException) {
-        super(wrappedException);
+        this(wrappedException, (Instant) null);
     }
 
     /**
@@ -55,7 +63,67 @@ public class DataExpiredException extends DataSealerException {
      * @param wrappedException exception to be wrapped by this one
      */
     public DataExpiredException(@Nullable final String message, @Nullable final Exception wrappedException) {
-        super(message, wrappedException);
+        this(message, wrappedException, null);
+    }
+
+    /**
+     * Constructor
+     * .
+     * @param exp data expiration 
+     * 
+     * @since 9.3.0
+     */
+    public DataExpiredException(@Nullable final Instant exp) {
+        expiration = exp;
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param message exception message
+     * @param exp data expiration
+     *  
+     * @since 9.3.0
+     */
+    public DataExpiredException(@Nullable final String message, @Nullable final Instant exp) {
+        super(message);
+        expiration = exp;
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param wrappedException exception to be wrapped by this one
+     * @param exp data expiration 
+     *  
+     * @since 9.3.0
+     */
+    public DataExpiredException(@Nullable final Exception wrappedException, @Nullable final Instant exp) {
+        super(wrappedException);
+        expiration = exp;
     }
 
+    /**
+     * Constructor.
+     * 
+     * @param message exception message
+     * @param wrappedException exception to be wrapped by this one
+     * @param exp data expiration 
+     *  
+     * @since 9.3.0
+     */
+    public DataExpiredException(@Nullable final String message, @Nullable final Exception wrappedException,
+            @Nullable final Instant exp) {
+        super(message, wrappedException);
+        expiration = exp;
+    }
+    
+    /**
+     * Gets data expiration if known.
+     * 
+     * @return data expiration, or null
+     */
+    @Nullable public Instant getExpiration() {
+        return expiration;
+    }
 }
\ No newline at end of file
diff --git a/shib-security/src/main/java/net/shibboleth/shared/security/DataSealer.java b/shib-security/src/main/java/net/shibboleth/shared/security/DataSealer.java
index c7df148d..4022c0d8 100644
--- a/shib-security/src/main/java/net/shibboleth/shared/security/DataSealer.java
+++ b/shib-security/src/main/java/net/shibboleth/shared/security/DataSealer.java
@@ -219,6 +219,7 @@ public class DataSealer extends AbstractInitializableComponent {
      * @param wrapped the encoded blob
      * 
      * @return the decrypted data, if it's unexpired
+     * 
      * @throws DataSealerException if the data cannot be unwrapped and verified
      */
     @Nonnull public String unwrap(@Nonnull @NotEmpty final String wrapped) throws DataSealerException {
@@ -233,6 +234,7 @@ public class DataSealer extends AbstractInitializableComponent {
      * @param keyUsed a buffer to receive the alias of the key used to encrypt the data
      * 
      * @return the decrypted data, if it's unexpired
+     * 
      * @throws DataSealerException if the data cannot be unwrapped and verified
      */
     @Nonnull public String unwrap(@Nonnull @NotEmpty final String wrapped, @Nullable final StringBuffer keyUsed)
@@ -310,11 +312,11 @@ public class DataSealer extends AbstractInitializableComponent {
      * @param decryptedLen length of data in the buffer
      * 
      * @return the decoded data if it is valid and unexpired
+     * 
      * @throws DataSealerException if the data cannot be unwrapped and verified
      */
     @Nonnull private String extractAndCheckDecryptedData(@Nonnull @NotEmpty final byte[] decryptedBytes,
-            final int decryptedOffset, final int decryptedLen)
-            throws DataSealerException {
+            final int decryptedOffset, final int decryptedLen) throws DataSealerException {
         
         try (final DataInputStream dataInputStream =
                 new DataInputStream(
@@ -324,7 +326,8 @@ public class DataSealer extends AbstractInitializableComponent {
             final long decodedExpirationTime = dataInputStream.readLong();
             if (decodedExpirationTime > 0 && System.currentTimeMillis() > decodedExpirationTime) {
                 log.debug("Unwrapped data has expired");
-                throw new DataExpiredException("Unwrapped data has expired");
+                throw new DataExpiredException("Unwrapped data has expired",
+                        Instant.ofEpochMilli(decodedExpirationTime));
             }
 
             final StringBuffer accumulator = new StringBuffer();
@@ -354,7 +357,9 @@ public class DataSealer extends AbstractInitializableComponent {
      * Equivalent to {@link #wrap(String, Instant)} with expiration set to "never".
      * 
      * @param data the data to wrap
+     * 
      * @return the encoded blob
+     * 
      * @throws DataSealerException if the wrapping operation fails
      */
     @Nonnull public String wrap(@Nonnull @NotEmpty final String data) throws DataSealerException {
@@ -376,7 +381,9 @@ public class DataSealer extends AbstractInitializableComponent {
      * 
      * @param data the data to wrap
      * @param exp expiration time or null for none
+     * 
      * @return the encoded blob
+     * 
      * @throws DataSealerException if the wrapping operation fails
      */
     @Nonnull public String wrap(@Nonnull @NotEmpty final String data, @Nullable final Instant exp)

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list