Class AnkaSecureSdk

java.lang.Object
co.ankatech.ankasecure.sdk.AnkaSecureSdk

public class AnkaSecureSdk extends Object

AnkaSecureSdk

High-level facade for interacting with the Anka Secure REST API. To use any cryptographic or key-management operations, you must first authenticate either as an application or as a user. Until authenticateApplication(String, String) or authenticateUser(String, String, String) completes successfully, all subsequent calls will fail with an authentication error.

Typical initialization and authentication


 // 1. Load CLI configuration
 Properties props = new Properties();
 try (var in = new FileInputStream("cli.properties")) {
     props.load(in);
 }

 // 2. Construct SDK
 AnkaSecureSdk sdk = new AnkaSecureSdk(props);

 // 3a. Authenticate as an application
 sdk.authenticateApplication("myClientId", "myClientSecret");

 // — or —

 // 3b. Authenticate as a user
 sdk.authenticateUser("[email protected]", "mypassword123", "tenantId123");
 

The cli.properties file must define all required parameters for the underlying OpenAPI client (endpoints, timeouts, logging levels, etc.). For detailed configuration options and examples, see AnkaTech CLI Configuration Guide.

See Also:
  • Constructor Details

    • AnkaSecureSdk

      public AnkaSecureSdk(Properties cliProperties)
      Constructs the SDK using the provided CLI properties.

      Typical properties include:

      • api.baseUrl – URL of the Anka Secure API gateway
      • api.timeoutMs – request timeout in milliseconds
      • logging.level – SDK and HTTP client log level
      • …other provider-specific flags…

      Use this constructor to bootstrap the SDK before authenticating. If the properties file is missing or malformed, an IOException will be thrown when loading it.

      
       Properties cliProps = new Properties();
       try (var stream = new FileInputStream("cli.properties")) {
           cliProps.load(stream);
       }
       AnkaSecureSdk sdk = new AnkaSecureSdk(cliProps);
       
      Parameters:
      cliProperties - properties loaded from your cli.properties file initialized
    • AnkaSecureSdk

      public AnkaSecureSdk(String accessToken, Properties cliProperties) throws AnkaSecureSdkException
      Constructs the SDK with a manually provided access token (bypassing authentication).

      This is useful for scenarios where the token is obtained externally, for example, during debug or in trusted system-to-system calls.

      NOTE: This constructor bypasses the call to authenticateApplication() and assumes the provided token is already valid. It is your responsibility to ensure proper token lifetime and renewal.

      Parameters:
      accessToken - a valid Bearer token to use for all API requests
      cliProperties - properties loaded from your cli.properties file
      Throws:
      AnkaSecureSdkException - if the OpenAPI client cannot be initialized
  • Method Details

    • authenticateApplication

      public void authenticateApplication(String clientId, String clientSecret) throws AnkaSecureSdkException
      Authenticates an application using client credentials (clientId/clientSecret). After calling this, future operations in the same AnkaSecureSdk instance will include the appropriate authentication token.
      Parameters:
      clientId - the client ID issued by the Anka Secure platform
      clientSecret - the client secret associated with the client ID
      Throws:
      AnkaSecureSdkException - if authentication fails for any reason
    • authenticateUser

      public void authenticateUser(String username, String password, String tenantId) throws AnkaSecureSdkException
      Authenticates a user by username/password. In scenarios where user-level context is required, use this method instead of authenticateApplication(String, String).
      Parameters:
      username - the username
      password - the user password
      Throws:
      AnkaSecureSdkException - if authentication fails
    • encrypt

      public EncryptResult encrypt(String kid, byte[] plaintext) throws AnkaSecureSdkException
      Encrypts an in-memory payload with the public key kid.

      The plaintext bytes never touch disk: they are Base64-encoded in memory and sent to the Anka Secure platform in a single request. The response is a Compact JWE (five Base64URL-encoded segments: header, encrypted key, IV, ciphertext, tag) which you can retrieve via EncryptResult.getJweToken().

      Usage example

      
       byte[] data = Files.readAllBytes(Path.of("document.pdf"));
       EncryptResult result = sdk.encrypt("myKid123", data);
       String jwe = result.getJweToken();
       // You may store `jwe` for later decryption or pass it to any JWE library
       
      Parameters:
      kid - identifier of the public key in the Anka Secure keystore (must not be null)
      plaintext - the raw bytes to encrypt (must not be null)
      Returns:
      a non-null EncryptResult containing:
      • jweToken: the Compact JWE string
      • keyRequested / actualKeyUsed
      • algorithmUsed
      • warnings
      Throws:
      AnkaSecureSdkException - if validation fails or the API call errors
    • encryptFile

      public EncryptResult encryptFile(String kid, Path input, Path output) throws AnkaSecureSdkException
      Encrypts the contents of a file with the public key kid.

      The SDK reads the file at input, sends it to the platform, then writes the resulting Compact JWE (five Base64URL segments) verbatim to output (UTF-8). All envelope metadata (keys, algorithms, warnings) is available in the returned EncryptResult.

      Usage example

      
       Path in = Path.of("report.txt");
       Path out = Path.of("report.txt.jwe");
       EncryptResult result = sdk.encryptFile("myKid123", in, out);
       // inspect metadata
       System.out.println("Used key: " + result.getActualKeyUsed());
       
      Parameters:
      kid - identifier of the public key in Anka Secure (not null)
      input - path to the plaintext file to be encrypted (not null)
      output - path where the Compact JWE will be written (not null)
      Returns:
      a non-null EncryptResult with:
      • jweToken
      • keyRequested / actualKeyUsed
      • algorithmUsed
      • warnings
      Throws:
      AnkaSecureSdkException - if any precondition is violated, the remote call fails, or writing to output errors. The exception context always includes kid, input, and output.
    • encryptFileStream

      public EncryptResult encryptFileStream(String kid, Path input, Path output) throws AnkaSecureSdkException
      Encrypts a file in streaming mode using the public key kid. Data is streamed directly from input to the platform and back into output, so the JVM heap never holds the entire payload.

      The service returns a Compact JWE envelope header in HTTP headers, and the ciphertext bytes in the response body. The SDK writes the bytes to output and returns an EncryptResult containing the same metadata fields as the non-streaming API.

      Usage example

      
       Path in = Path.of("large-video.mp4");
       Path out = Path.of("large-video.mp4.jwe");
       EncryptResult meta = sdk.encryptFileStream("myKid123", in, out);
       // verify algorithm
       assert meta.getAlgorithmUsed().endsWith("+A256GCM");
       
      Parameters:
      kid - identifier of the public key in Anka Secure (not null)
      input - path to the plaintext file to be streamed (not null)
      output - path where ciphertext bytes will be streamed (not null)
      Returns:
      a non-null EncryptResult with:
      • jweToken
      • keyRequested / actualKeyUsed
      • algorithmUsed
      • warnings
      Throws:
      AnkaSecureSdkException - if validation fails, the server returns non-200, or an I/O error occurs while streaming. The exception context includes kid, input, and output.
    • decrypt

      public DecryptResult decrypt(String ciphertextJwe) throws AnkaSecureSdkException
      Decrypts an in-memory Compact JWE.

      The input must be a full Compact JWE string (five Base64URL-encoded segments: header, encrypted key, IV, ciphertext, authentication tag). The SDK sends it to the Anka Secure platform, which uses the embedded header to resolve the correct private key, then returns both raw plaintext bytes and full metadata in a DecryptResult.

      Usage example

      
       String jwe = FileIO.readUtf8(Path.of("message.jwe"));
       DecryptResult result = sdk.decrypt(jwe);
       byte[] data = result.getPlaintext();
       DecryptResultMetadata meta = result.getMeta();
       System.out.println("Decrypted with key: " + meta.getActualKeyUsed());
       
      Parameters:
      ciphertextJwe - the full Compact JWE text (UTF-8) – five Base64URL segments separated by dots (must not be null)
      Returns:
      a DecryptResult containing:
      Throws:
      AnkaSecureSdkException - if the input is null, invalid, or the API call fails
    • decryptFile

      public DecryptResultMetadata decryptFile(Path input, Path output) throws AnkaSecureSdkException
      Decrypts a Compact JWE stored in a file.

      The SDK reads the file at input, parses the Compact JWE (five Base64URL segments), and sends it to the platform. The platform resolves the private key from the JWE header and returns plaintext bytes, which the SDK writes to output. A DecryptResultMetadata is returned containing full metadata (keyRequested, actualKeyUsed, algorithmUsed, warnings).

      Usage example

      
       Path jweFile = Path.of("secret.jwe");
       Path clearFile = Path.of("secret.pdf");
       DecryptResultMetadata result = sdk.decryptFile(jweFile, clearFile);
       System.out.println("Used algorithm: " + result.getAlgorithmUsed());
       
      Parameters:
      input - path to the UTF-8 file containing the Compact JWE (must not be null)
      output - path where decrypted bytes will be written (must not be null)
      Returns:
      a non-null DecryptResultMetadata with:
      • jweToken: the original JWE string
      • keyRequested / actualKeyUsed
      • algorithmUsed
      • warnings
      Throws:
      AnkaSecureSdkException - if input or output is null, unreadable, the API call fails, or writing to output errors. Exception context includes input and output.
    • decryptFileStream

      public DecryptResultMetadata decryptFileStream(Path input, Path output) throws AnkaSecureSdkException
      Decrypts a ciphertext in streaming mode using a multipart JWET.

      The input file must contain a JWET envelope (JSON streaming JWE with separate header and encrypted chunks). The SDK streams the bytes of input to the platform, which resolves the key and decrypts each chunk on the fly. Decrypted bytes are streamed directly to output, keeping JVM memory usage constant. Returns DecryptResultMetadata with metadata only.

      Usage example

      
       Path jwetFile = Path.of("large-data.jwet");
       Path outFile  = Path.of("large-data.bin");
       DecryptResultMetadata meta = sdk.decryptFileStream(jwetFile, outFile);
       // meta.getActualKeyUsed(), meta.getWarnings(), etc.
       
      Parameters:
      input - path to the multipart JWET file (must not be null)
      output - path where plaintext bytes will be streamed (must not be null)
      Returns:
      a non-null DecryptResultMetadata containing:
      • keyRequested / actualKeyUsed
      • algorithmUsed
      • warnings
      (ciphertext itself is written to output)
      Throws:
      AnkaSecureSdkException - if input or output is null, unreadable, the server returns non-200, or an I/O error occurs while streaming. Exception context contains input and output.
    • reencrypt

      public ReencryptResult reencrypt(String newKid, String jweCiphertext) throws AnkaSecureSdkException
      Re-encrypts an in-memory Compact JWE so it is protected by a different key.

      The input must be the full Compact JWE string (five Base64URL segments: header, encrypted key, IV, ciphertext, tag). The SDK sends it to the Anka Secure platform, which:

      1. Decrypts using the private key referenced in the JWE header.
      2. Encrypts with the public key identified by newKid.
      The resulting Compact JWE is returned in a ReencryptResult containing metadata for both the old and new keys.

      Usage example

      
       String oldJwe = FileIO.readUtf8(Path.of("secret.jwe"));
       ReencryptResult result = sdk.reencrypt("newKid123", oldJwe);
       String newJwe = result.getJweToken();
       System.out.println("Re-encrypted with key: " + result.getNewKeyUsed());
       
      Parameters:
      newKid - identifier of the public key to protect the data after re-encryption (must not be null)
      jweCiphertext - the full Compact JWE text to re-encrypt (must not be null)
      Returns:
      a non-null ReencryptResult with:
      • jweToken: the new Compact JWE string
      • old/new keyRequested, actualKeyUsed, algorithmUsed
      • warnings
      Throws:
      AnkaSecureSdkException - if either argument is null, or the API call fails (exception context includes newKid)
    • reencryptFile

      public ReencryptResult reencryptFile(String newKid, Path input, Path output) throws AnkaSecureSdkException
      Re-encrypts a Compact JWE file so it is protected by newKid.

      The SDK reads the existing Compact JWE from input, sends it to the platform for decryption and re-encryption, then writes the new Compact JWE verbatim to output. Returns metadata for both the old and new keys in a ReencryptResult.

      Usage example

      
       Path in  = Path.of("encrypted.jwe");
       Path out = Path.of("rotated.jwe");
       ReencryptResult result = sdk.reencryptFile("newKid123", in, out);
       System.out.println("Old key: " + result.getOldKeyUsed());
       System.out.println("New key: " + result.getNewKeyUsed());
       
      Parameters:
      newKid - identifier of the public key to protect the data after rotation (must not be null)
      input - path to the existing Compact JWE file (must not be null)
      output - path where the refreshed Compact JWE will be written (must not be null)
      Returns:
      a non-null ReencryptResult containing:
      • jweToken
      • old/new keyRequested, actualKeyUsed, algorithmUsed
      • warnings
      Throws:
      AnkaSecureSdkException - if validation fails, the HTTP call is unsuccessful, or writing to output errors (context includes newKid, input, output)
    • reencryptFileStream

      public ReencryptResult reencryptFileStream(String newKid, Path input, Path output) throws AnkaSecureSdkException
      Re-encrypts a detached-ciphertext JWE (JWET General JSON + binary envelope) in streaming mode – managed flow.

      The SDK streams the two-part artifact located at input to the server:

      1. Part 1 – application/jose+json: a JWET header whose ciphertext and tag fields are null (detached).
      2. Part 2 – application/octet-stream: the proprietary envelope [wkLen]‖wrappedKey‖[ivLen]‖iv‖ciphertext‖tag.

      The platform decrypts the payload with the private key referenced by the embedded kid and immediately encrypts it with newKid. Header + ciphertext are streamed chunk-by-chunk to output, so memory usage stays flat even for very large files. Metadata about both keys is returned in a ReencryptResult.

      Usage example

      
       Path in  = Path.of("video.jwet");          // header+envelope
       Path out = Path.of("video_rotated.jwet");
      
       ReencryptResult meta =
               sdk.reencryptFileStream("mlkemKid", in, out);
      
       System.out.println("New algorithm = "
                          + meta.getNewKeyAlgorithmUsed());
       
      Parameters:
      newKid - key identifier that must protect the data after rotation (must not be null)
      input - JWET file previously produced by encryptFileStream (must not be null)
      output - destination path for the refreshed ciphertext (must not be null)
      Returns:
      never null; see ReencryptResult for details
      Throws:
      AnkaSecureSdkException - if validation, network, or I/O fails
    • reencryptFileStream

      public ReencryptResult reencryptFileStream(String newKid, String sourceKidOverride, Path input, Path output) throws AnkaSecureSdkException
      Re-encrypts a detached-ciphertext JWE (JWET General JSON + binary envelope) in streaming mode.

      Decryption is performed with:

      • the kid present in the JWET header (managed flow), or
      • the optional sourceKidOverride supplied here when the header lacks a kid (migration flow – legacy RSA/EC artifacts, utility encryptions, etc.).

      The server immediately encrypts the plaintext with newKid and streams the refreshed header and ciphertext to output. The returned ReencryptResult exposes:

      • metadata for both old and new keys,
      • any non-fatal warnings,
      • migrationMode  – true when sourceKidOverride was applied.

      Usage example – migration flow

      
       Path legacyCt = Path.of("rsa_legacy.jwet");
       Path rotated  = Path.of("pqc_rotated.jwet");
      
       ReencryptResult meta = sdk.reencryptFileStream(
               "mlkem768Kid",        // new key
               "legacyRsaKid",       // sourceKidOverride
               legacyCt,
               rotated);
      
       if (meta.isMigrationMode()) {
           System.out.println("Legacy ciphertext upgraded!");
       }
       
      Parameters:
      newKid - key identifier that must protect the data after rotation (must not be null)
      sourceKidOverride - optional key identifier used only when the JWET header lacks a kid; pass null for the normal managed flow
      input - JWET file produced by encryptFileStream (must not be null)
      output - destination path for the refreshed ciphertext (must not be null)
      Returns:
      never null; see ReencryptResult for details
      Throws:
      AnkaSecureSdkException - if validation, network, or I/O fails
    • sign

      public SignResult sign(String kid, byte[] data) throws AnkaSecureSdkException
      Signs an in-memory payload with the private key kid.

      The SDK sends the raw bytes to the Anka Secure platform, which computes a detached Compact JWS signature (three Base64URL-encoded segments: header, payload, signature). The returned SignResult lets you inspect:

      • jwsToken: the full Compact JWS string
      • keyRequested / actualKeyUsed
      • algorithmUsed
      • warnings

      Usage example

      
       byte[] data = Files.readAllBytes(Path.of("document.pdf"));
       SignResult result = sdk.sign("myKid123", data);
       String jws = result.getJwsToken();
       // verify or transmit `jws` as needed
       
      Parameters:
      kid - identifier of the private key in Anka Secure (must not be null)
      data - raw bytes to sign (must not be null)
      Returns:
      a non-null SignResult containing:
      • jwsToken
      • keyRequested / actualKeyUsed
      • algorithmUsed
      • warnings
      Throws:
      AnkaSecureSdkException - if validation fails or the API call errors
    • signFile

      public SignResult signFile(String kid, Path input, Path signature) throws AnkaSecureSdkException
      Generates a Compact JWS by signing the contents of a file.

      The SDK reads the file at input, streams it to the platform for detached signing, and writes the resulting JWS string to signature (UTF-8). The returned SignResult exposes the same metadata fields as the in-memory API.

      Usage example

      
       Path in  = Path.of("report.txt");
       Path sig = Path.of("report.txt.jws");
       SignResult result = sdk.signFile("myKid123", in, sig);
       // log rotation warnings
       result.getWarnings().forEach(System.out::println);
       
      Parameters:
      kid - identifier of the private key in Anka Secure (not null)
      input - path to the file whose contents will be signed (not null)
      signature - destination path for the detached JWS string (not null)
      Returns:
      a non-null SignResult containing:
      • jwsToken
      • keyRequested / actualKeyUsed
      • algorithmUsed
      • warnings
      Throws:
      AnkaSecureSdkException - if validation fails, the server returns an error, or writing the JWS file fails
    • signFileStream

      public SignResult signFileStream(String kid, Path input, Path signature) throws AnkaSecureSdkException
      Signs a file in streaming mode with the private key kid. Detached-JWS bytes are streamed to signature, and a SignResult is returned for metadata inspection.

      This method is optimized for large files: it never loads the entire payload into memory, streaming both the input file and the resulting signature directly.

      Usage example

      
       Path in  = Path.of("large-video.mp4");
       Path sig = Path.of("large-video.mp4.jws");
       SignResult meta = sdk.signFileStream("myKid123", in, sig);
       System.out.println("Signature algorithm: " + meta.getAlgorithmUsed());
       
      Parameters:
      kid - identifier of the private key in Anka Secure (not null)
      input - path to the file to be signed (not null)
      signature - destination path where the detached-JWS bytes will be streamed (not null)
      Returns:
      a non-null SignResult containing:
      • jwsToken
      • keyRequested / actualKeyUsed
      • algorithmUsed
      • warnings
      Throws:
      AnkaSecureSdkException - if validation fails, the server responds with non-200, or an I/O error occurs while streaming
    • verifySignature

      public VerifySignatureResult verifySignature(Path jwsFile) throws AnkaSecureSdkException
      Verifies a Compact JWS stored in a UTF-8 file.

      Reads the file at jwsFile, sends the full Compact JWS (three Base64URL segments: header, payload, signature) to the Anka Secure platform, and returns a VerifySignatureResult containing:

      • valid – whether the signature matches and passes server-side policy checks;
      • keyRequested / actualKeyUsed;
      • algorithmUsed;
      • warnings – any soft-limit or expiry advisories.

      Usage example

      
       Path jwsFile = Path.of("document.pdf.jws");
       VerifySignatureResult result = sdk.verifySignature(jwsFile);
       if (!result.isValid()) {
           System.err.println("Signature invalid or key expired");
       }
       
      Parameters:
      jwsFile - path to the UTF-8 file containing the Compact JWS (must not be null)
      Returns:
      a non-null VerifySignatureResult
      Throws:
      AnkaSecureSdkException - if jwsFile is null or unreadable, the remote call fails, or an I/O error occurs. Context includes jwsFile.
    • verifySignature

      public VerifySignatureResult verifySignature(String jws) throws AnkaSecureSdkException
      Verifies an in-memory Compact JWS string.

      Sends the provided JWS text (three Base64URL segments separated by dots) to the Anka Secure platform. Returns a VerifySignatureResult with the same metadata fields as the file-based API.

      Usage example

      
       String jws = FileIO.readUtf8(Path.of("document.pdf.jws"));
       VerifySignatureResult result = sdk.verifySignature(jws);
       System.out.println("Verified with key: " + result.getActualKeyUsed());
       
      Parameters:
      jws - the full Compact JWS text (must not be null)
      Returns:
      a non-null VerifySignatureResult
      Throws:
      AnkaSecureSdkException - if jws is null, invalid, or the API call fails
    • verifySignatureStream

      public VerifySignatureResult verifySignatureStream(Path input, Path detachedJwsFile) throws AnkaSecureSdkException
      Verifies a detached-JWS signature in streaming mode.

      The detached JWS (General JSON with a null payload) is read from detachedJwsFile and streamed to the Anka Secure platform alongside the binary payload read from input. The platform uses the kid in the header to fetch the public key, then validates the signature. Returns a VerifySignatureResult containing:

      • valid;
      • keyRequested / actualKeyUsed;
      • algorithmUsed;
      • warnings.

      Usage example

      
       Path payload = Path.of("report.pdf");
       Path sigFile = Path.of("report.pdf.sig");
       VerifySignatureResult result = sdk.verifySignatureStream(payload, sigFile);
       if (!result.isValid()) {
           System.err.println("Detached signature check failed");
       }
       
      Parameters:
      input - path to the binary payload file (must not be null)
      detachedJwsFile - path to the UTF-8 file containing the detached-JWS JSON (must not be null)
      Returns:
      a non-null VerifySignatureResult
      Throws:
      AnkaSecureSdkException - if either argument is null, unreadable, the API call fails, or an I/O error occurs. Context includes both paths.
    • resign

      public ResignResult resign(String newKid, String oldJws) throws AnkaSecureSdkException
      Generates a fresh Compact JWS for the payload embedded in an existing JWS.

      The SDK sends the old Compact JWS string to the Anka Secure platform, which:

      1. Verifies the old signature using the private key referenced in its header.
      2. Re-signs the extracted payload with the private key identified by newKid.
      Returns a ResignResult containing the new Compact JWS plus metadata for both old and new keys (requested/actual KIDs, algorithms, warnings).

      Usage example

      
       String oldJws = FileIO.readUtf8(Path.of("document.jws"));
       ResignResult result = sdk.resign("newKid123", oldJws);
       String newJws = result.getJwsToken();
       System.out.println("Re-signed with key: " + result.getNewKeyUsed());
       
      Parameters:
      newKid - identifier of the private key to sign the new JWS (must not be null)
      oldJws - the full Compact JWS text to re-sign (must not be null)
      Returns:
      a non-null ResignResult with:
      • jwsToken: the new Compact JWS string
      • old/new KIDs and algorithms
      • warnings
      Throws:
      AnkaSecureSdkException - if either argument is null or the API call fails
    • resignFile

      public ResignResult resignFile(String newKid, Path oldJws, Path newJws) throws AnkaSecureSdkException
      Re-signs a file-based Compact JWS.

      Reads the old JWS from oldJws, sends it to the platform for verification and re-signing, and writes the refreshed JWS to newJws. Returns a ResignResult with full dual-key metadata and warnings.

      Usage example

      
       Path oldJwsFile = Path.of("report.jws");
       Path newJwsFile = Path.of("report-resigned.jws");
       ResignResult result = sdk.resignFile("newKid123", oldJwsFile, newJwsFile);
       System.out.println("Old key used: " + result.getOldKeyUsed());
       
      Parameters:
      newKid - identifier of the private key to sign the new JWS (must not be null)
      oldJws - path to the existing Compact JWS file (must not be null)
      newJws - destination path for the refreshed Compact JWS (must not be null)
      Returns:
      a non-null ResignResult containing:
      • jwsToken
      • old/new KIDs and algorithms
      • warnings
      Throws:
      AnkaSecureSdkException - if validation fails, the API call errors, or writing to newJws fails. Context includes newKid, oldJws, newJws.
    • resignFileStream

      public ResignResult resignFileStream(String newKid, Path oldDetachedJwsFile, Path input, Path newDetachedJwsFile) throws AnkaSecureSdkException
      Re-signs a detached-JWS signature in streaming mode.

      Streams the old detached-JWS (header+signature JSON) from oldDetachedJwsFile and the binary payload from input to the platform, which:

      1. Verifies the old signature (oldKid inferred from header).
      2. Emits a fresh detached-JWS for the same payload using newKid.
      Writes the new detached-JWS to newDetachedJwsFile and returns a ResignResult with dual-key metadata and warnings.

      Usage example

      
       Path payload       = Path.of("data.bin");
       Path oldSigFile    = Path.of("data.sig");
       Path newSigFile    = Path.of("data-resigned.sig");
       ResignResult result = sdk.resignFileStream(
           "newKid123", oldSigFile, payload, newSigFile);
       System.out.println("New algorithm: " + result.getNewKeyAlgorithmUsed());
       
      Parameters:
      newKid - identifier of the private key to sign the new detached-JWS (must not be null)
      oldDetachedJwsFile - path to the existing detached-JWS file (General JSON, no payload) (must not be null)
      input - path to the binary payload that was originally signed (must not be null)
      newDetachedJwsFile - destination path for the refreshed detached-JWS JSON (must not be null)
      Returns:
      a non-null ResignResult containing:
      • jwsToken
      • old/new KIDs and algorithms
      • warnings
      Throws:
      AnkaSecureSdkException - if a pre-condition is violated, the streaming call fails, or writing to newDetachedJwsFile fails. Context includes newKid, oldDetachedJwsFile, input, newDetachedJwsFile.
    • verifySignatureUtilityStream

      public VerifySignatureResult verifySignatureUtilityStream(String kty, String alg, String publicKeyBase64, String signatureBase64, Path input) throws AnkaSecureSdkException
      Verifies a detached signature in streaming mode using an external public key—no keystore lookup is performed.

      Streams the binary payload at input along with:

      • kty: JWK key type (e.g. “RSA”, “ML-DSA”)
      • alg: algorithm or parameter-set identifier understood by the platform
      • publicKeyBase64: Base64-encoded public key bytes
      • signatureBase64: Base64-encoded detached-JWS signature
      The platform performs the cryptographic check and returns a VerifySignatureResult containing:
      • valid – boolean verification outcome
      • algorithmUsed – actual algorithm negotiated
      • warnings – any non-fatal advisories (soft-limit, expiry)

      Usage example

      
       Path payload = Path.of("data.bin");
       String pubKey = FileIO.readUtf8(Path.of("pubkey.b64"));
       String sig    = FileIO.readUtf8(Path.of("data.sig.b64"));
       VerifySignatureResult result = sdk.verifySignatureUtilityStream(
           "RSA", "RSA-2048+SHA256", pubKey, sig, payload);
       if (!result.isValid()) {
           System.err.println("External signature verification failed");
       }
       
      Parameters:
      kty - JWK key type (must not be null)
      alg - algorithm/parameter-set identifier (must not be null)
      publicKeyBase64 - Base64-encoded public key bytes (must not be null)
      signatureBase64 - Base64-encoded detached-JWS signature (must not be null)
      input - path to the data file that was signed (must not be null)
      Returns:
      a non-null VerifySignatureResult with verification outcome and metadata
      Throws:
      AnkaSecureSdkException - if any argument is null, local validation fails, the remote call errors, or an I/O problem occurs. Exception context includes kty, alg, and input.
    • encryptFileUtilityStream

      public EncryptResult encryptFileUtilityStream(String kty, String alg, String publicKeyBase64, Path input, Path output) throws AnkaSecureSdkException
      Encrypts a local file in streaming mode with an externally supplied public key—no keystore lookup is performed.

      Streams plaintext bytes from input to the platform, which uses the provided:

      • kty: JWK key type (e.g. “RSA”, “ML-KEM”)
      • alg: algorithm or parameter-set identifier (e.g. “RSA-2048”)
      • publicKeyBase64: Base64-encoded raw public key
      to produce a combined JWE envelope (header + ciphertext chunks). The SDK writes the ciphertext stream to output and returns an EncryptResult containing:
      • algorithmUsed – negotiated content-encryption alg
      • warnings – any soft-limit alerts

      Usage example

      
       Path in      = Path.of("large-file.dat");
       Path out     = Path.of("large-file.jwe");
       String pub   = FileIO.readUtf8(Path.of("pubkey.b64"));
       EncryptResult meta = sdk.encryptFileUtilityStream(
           "ML-KEM", "ML-KEM-1024+A256GCM", pub, in, out);
       System.out.println("Content encrypted with: " + meta.getAlgorithmUsed());
       
      Parameters:
      kty - JWK key type (must not be null)
      alg - algorithm/parameter-set identifier (must not be null)
      publicKeyBase64 - Base64-encoded public key (must not be null)
      input - path to the plaintext file (must not be null)
      output - path where combined JWE will be written (must not be null)
      Returns:
      a non-null EncryptResult with metadata only (ciphertext is streamed to output)
      Throws:
      AnkaSecureSdkException - if any argument is null, local validation fails, the remote streaming call errors, or writing to output fails. Exception context includes kty, alg, input, and output.
    • exportKey

      public void exportKey(String kid, Path output) throws AnkaSecureSdkException
      Exports a key’s JSON representation to a file.

      Retrieves the key identified by kid from the Anka Secure platform and writes its full JSON spec—including public and private material (if permitted) and all metadata—to output (UTF-8).

      Usage example

      
       Path outFile = Path.of("myKey.json");
       sdk.exportKey("myKid123", outFile);
       // Now inspect myKey.json for |kty|, |alg|, |keyOps|, expiry, etc.
       
      Parameters:
      kid - the key identifier on the Anka Secure platform (must not be null)
      output - destination file path where the JSON will be written (must not be null)
      Throws:
      AnkaSecureSdkException - if kid or output is null, the API request fails, or local I/O to write the file fails. Context map includes kid.
    • exportKey

      public ExportedKeySpec exportKey(String kid) throws AnkaSecureSdkException
      Exports a key’s specification as a Java object.

      Retrieves the key identified by kid and returns it as an ExportedKeySpec, containing full metadata and public key bytes (and private bytes if the key is exportable).

      Usage example

      
       ExportedKeySpec spec = sdk.exportKey("myKid123");
       System.out.println("Algorithm: " + spec.getAlg());
       
      Parameters:
      kid - the key identifier to export (must not be null)
      Returns:
      a fully populated ExportedKeySpec with key material and metadata
      Throws:
      AnkaSecureSdkException - if kid is null, the remote call fails, or parsing errors occur. The exception’s context map always includes kid.
    • importPrivateKeyPkcs12

      public void importPrivateKeyPkcs12(Pkcs12ImportSpec p12spec) throws AnkaSecureSdkException
      Imports a Base64-encoded PKCS#12 (.p12) blob as a new private key.

      Use when you have a PKCS#12 bundle (Base64 string) possibly protected by a password. The Pkcs12ImportSpec must include:

      • kid: desired key ID
      • p12Base64: Base64-encoded PKCS#12 data
      • password: optional password if the bundle is encrypted

      Usage example

      
       Pkcs12ImportSpec spec = new Pkcs12ImportSpec("myKid", b64Data, "p@ssw0rd");
       sdk.importPrivateKeyPkcs12(spec);
       
      Parameters:
      p12spec - the import specification containing kid, Base64-encoded PKCS#12 data, and optional password (must not be null)
      Throws:
      AnkaSecureSdkException - if p12spec is null, the API call fails, or the PKCS#12 data is invalid. Context includes p12spec.getKid().
    • patchKey

      public void patchKey(String kid, PatchKeySpec patchSpec) throws AnkaSecureSdkException
      Applies a JSON Merge-Patch to update expiry and usage-limit fields.

      Example:

      
       PatchKeySpec patch = new PatchKeySpec.Builder()
           .expiresAt(Instant.parse("2030-05-31T23:59:59Z"))
           .softUsageLimit(40000)
           .build();
      
       sdk.patchKey("my_MLKEM_Key", patch);
       

      Parameters:
      kid - the key identifier to patch (not null)
      patchSpec - spec object containing the fields to update (not null)
      Throws:
      AnkaSecureSdkException - if kid or patchSpec is null, or the server rejects the patch. Context includes kid.
    • generateKey

      public void generateKey(GenerateKeySpec spec) throws AnkaSecureSdkException
      Creates a new cryptographic key in the Anka Secure platform using parameters from GenerateKeySpec. Supports classical and PQC algorithms, as well as symmetric keys.
      Parameters:
      spec - the specification object containing kid, kty, alg, optional key operations, exportability, and usage constraints
      Throws:
      AnkaSecureSdkException - if the API call fails (e.g., invalid params, network error)
    • importKey

      public void importKey(ImportKeySpec keyData) throws AnkaSecureSdkException
      Imports an existing key by providing its fields in a ImportKeySpec. One can import a public key, private key, or both, along with key usage restrictions, expiration times, and usage limits.
      Parameters:
      keyData - an ImportKeySpec containing all necessary metadata and key material
      Throws:
      AnkaSecureSdkException - if the API call fails (e.g., invalid format, server error)
    • listKeys

      public String listKeys() throws AnkaSecureSdkException
      Lists every key currently stored in the Anka Secure keystore and returns a readable summary.

      Internally calls GET /api/key‑management/keys through the generated OpenAPI client.

      Returns:
      a multi‑line String containing a header with the total count followed by one line per key showing kid, key‑type and algorithm
      Throws:
      AnkaSecureSdkException - if the request fails in any way
    • removeKey

      public void removeKey(String kid) throws AnkaSecureSdkException
      Removes a key (by kid) from the keystore. This is irreversible.
      Parameters:
      kid - the key ID to remove
      Throws:
      AnkaSecureSdkException - if the API call fails
    • revokeKey

      public void revokeKey(String kid) throws AnkaSecureSdkException
      Revokes a key by kid. Once revoked, the key cannot be used for future encryption/signing, and its status becomes "REVOKED."
      Parameters:
      kid - the key ID to revoke
      Throws:
      AnkaSecureSdkException - if the API call fails
    • createRotation

      public ExportedKeySpec createRotation(String kid, GenerateKeySpec successor) throws AnkaSecureSdkException
      Creates a successor key for kid and, optionally, schedules the rotation for a future instant.

      Internally invokes
      POST /api/key‑management/keys/{kid}/rotations.

      Parameters:
      kid - identifier of the key that will be rotated
      successor - specification of the successor key (same fields accepted by generateKey(GenerateKeySpec))
      Returns:
      an ExportedKeySpec describing the newly generated key when the server performs the rotation synchronously (HTTP 200); returns null if the server replies with HTTP 202 Accepted and creates an asynchronous job
      Throws:
      AnkaSecureSdkException - if the request fails
    • getSupportedAlgorithms

      public List<AlgorithmInfo> getSupportedAlgorithms() throws AnkaSecureSdkException
      Retrieves a list of supported algorithms from the server, returning them as a list of AlgorithmInfo (kty+alg).
      Returns:
      a list of AlgorithmInfo objects
      Throws:
      AnkaSecureSdkException - if the API call fails