Class EasySigner

java.lang.Object
de.hda.fbi.ucs.eucrite.EasySigner

public class EasySigner
extends Object
The EasySigner is a signer that can handle classical and quantum-safe (stateless and stateful) signature schemes. The keypair used for signing is handled by an instance of KeyManager. After initializing the EasySigner, no further interaction with the key material is needed, but possible.

Use withExistingKey(StorageParameters storageParameters) to initialize the EasySigner with an existing keypair, e.g. from an KeyStore file, or withNewKey(AlgorithmParameters algorithmParameters, StorageParameters storageParameters) to let the EasySigner create a new keypair with the parameters given by algorithmParamters. In both cases, storageParameters holds all the necessary information to load and store the keypair.

To find the right algorithmParamters, the eUCRITE API provides templates with fitting parameters for certain requirements or use cases, e.g. security levels. We recommend using these templates, especially for inexperienced users.

When using a stateful signature scheme like XMSS or XMSSMT, the statful key is automatically updated and stored at the specified storage location to ensure the same state is never used twice.

Example: Initializing the signer for RSA with a newly generated key pair, sign a message and verify the generated signature may look like this:

 
 String password = ...;
 AlgorithmParameters algorithmParameters = AlgorithmParameters.Template.Signature.Security_Level.MEDIUM.getParameters();
 KeystoreParameters keystoreParameters = new KeystoreParameters(new File("data/key"), password);
 EasySigner signer = EasySigner.withNewKey(algorithmParameters, keystoreParameters);
 String toBeSigned = "Sign me!";
 byte[] signature = signer.sign(toBeSigned.getBytes());
 signer.verify(toBeSigned.getBytes(), signature);
 
 
Author:
Alexander Zeier
  • Constructor Details

  • Method Details

    • withExistingKey

      public static EasySigner withExistingKey​(StorageParameters storageParameters) throws FileNotFoundException, NoSuchAlgorithmException
      Creates a EasySigner with existing key material. The location of the key material and other information to access the key material are given by the storageParameters.

      Example (loading the key material):

       
       KeystoreParameters keystoreParameters = new KeystoreParameters(new File("data/key"), "123456");
       EasySigner signer = EasySigner.withExistingKey(keystoreParameters);
       
       
      Parameters:
      storageParameters - The parameters defining the storage location and everything else necessary to access the key pair.
      Returns:
      The EasySigner
      Throws:
      FileNotFoundException - If the file couldn't be found.
      NoSuchAlgorithmException - If the key pair belongs to an algorithm that is not supported by this Signer.
    • withNewKey

      public static EasySigner withNewKey​(AlgorithmParameters algorithmParameters, StorageParameters storageParameters) throws FileAlreadyExistsException, NoSuchAlgorithmException
      Creates a EasySigner with a newly generated key pair. The location of the key pair and other information to access the key pair are given by the storageParameters. The algorithm to use with all necessary parameters are given by the algorithmParameters.

      Example (creating a key pair):

       
       AlgorithmParameters algorithmParameters = AlgorithmParameters.Template.Signature.Security_Level.MEDIUM.getParameters();
       KeystoreParameters keystoreParameters = new KeystoreParameters(new File("data/key"), "secure_password");
       EasySigner signer = EasySigner.withNewKey(algorithmParameters, keystoreParameters);
       
       
      Parameters:
      algorithmParameters - The parameters defining the signature algorithm with the necessary parameters.
      storageParameters - The parameters defining the storage location and everything else necessary to access the key material.
      Returns:
      An instance of the EasySigner.
      Throws:
      FileAlreadyExistsException - If the file already exists.
      NoSuchAlgorithmException - If the key pair belongs to an algorithm that is not supported by this Signer.
    • sign

      public byte[] sign​(byte[] toBeSigned)
      Sign the given byte[] toBeSigned.

      Depending on the type of KeyManager (StatelessKeyManager or StatefulKeyManager), a corresponding sign method is called. For the StatefulKeyManager, this signing method is synchronized to prevent concurrent signing with the stateful key. When using the StatefulKeyManager, the private key is updated after every call of the sign method and stored at the storage location specified in the KeyManager.

      The hash algorithm used to calculate the digest which is then signed instead of the byte[] toBeSigned is SHA256 by default.

      Signing a string message would look like this:

       
       byte[] toBeSigned = ...;
       byte[] signature = signer.sign(toBeSigned);
       
       
      Parameters:
      toBeSigned - The data that should be signed.
      Returns:
      The Signature in form of a byte array.
    • sign

      public byte[] sign​(InputStream toBeSigned) throws IOException
      Sign the given InputStream toBeSigned. An InputStream can be generated e.g. from an byte[] with ByteArrayInputStream or a File with FileInputStream.

      Depending on the type of keyManager (StatelessKeyManager or StatefulKeyManager), a corresponding sign method is called. For the StatefulKeyManager, this signing method is synchronized to prevent concurrent signing with the stateful key. When using the StatefulKeyManager, the private key is updated after every call of the sign method and stored at the storage location specified in the KeyManager.

      The hash algorithm used to calculate the digest which is then signed instead of the byte[] toBeSigned is SHA256 by default.

      Using the InputStream will leave it empty after signing is completed.

      Signing a file from disk would look like this:

       
       FileInputStream toBeSigned = new FileInputStream("data/file.txt");
       byte[] signature = signer.sign(toBeSigned);
       
       
      Parameters:
      toBeSigned - The data that should be signed.
      Returns:
      The Signature in form of a byte array.
      Throws:
      IOException - if no data from the given InputStream can be read.
    • signMultipleData

      public ArrayList<byte[]> signMultipleData​(InputStream... toBeSigned) throws IOException
      Sign one or more InputStreams toBeSigned. An InputStream can be generated e.g. from an byte[] with ByteArrayInputStream or a File with FileInputStream.

      Depending on the type of keyManager (StatelessKeyManager or StatefulKeyManager), a corresponding sign method is called. For the StatefulKeyManager, this signing method is synchronized to prevent concurrent signing with the stateful key. When using the StatefulKeyManager, the private key is updated for every data given in toBeSigned and then stored once at the location given in the StorageParameters before executing the signatures. This method should be used instead of implementing a loop to minimize the number of store operations and thus increase the performance.

      The hash algorithm used to calculate the digest which is then signed instead of the byte[] toBeSigned is SHA256 by default.

      Using the InputStream will leave it empty after signing is completed.

      Signing two files would look like this:

       
       FileInputStream toBeSigned1 = new FileInputStream("data/file1.txt");
       FileInputStream toBeSigned2 = new FileInputStream("data/file2.zip");
       ArrayList<byte[]> signatures = signer.signMultipleData(toBeSigned1, toBeSigned2);
       
       
      Parameters:
      toBeSigned - The data that should be signed. This can be one ore more InputStreams or an array of InputStreams.
      Returns:
      The Signatures in form of an array of a List of byte[]s.
      Throws:
      IOException - if no data from the given InputStream can be read.
    • signMultipleData

      public ArrayList<byte[]> signMultipleData​(byte[]... toBeSigned)
      Sign one or more byte[]s toBeSigned.

      Depending on the type of keyManager (StatelessKeyManager or StatefulKeyManager), a corresponding sign method is called. For the StatefulKeyManager, this signing method is synchronized to prevent concurrent signing with the stateful key. When using the StatefulKeyManager, the private key is updated for every data given in toBeSigned and then stored once at the location given in the StorageParameters before executing the signatures. This method should be used instead of implementing a loop to minimize the number of store operations and thus increase the performance.

      The hash algorithm used to calculate the digest which is then signed instead of the byte[] toBeSigned is SHA256 by default.

      Signing two string messages would look like this:

       
       byte[] toBeSigned1 = "Sign me!".getBytes();
       byte[] toBeSigned2 = "Sign me, too!".getBytes();
       ArrayList<byte[]> signatures = signer.signMultipleData(toBeSigned1, toBeSigned2);
       
       
      Parameters:
      toBeSigned - The data that should be signed. This could be one or more byte[] or an array of byte[].
      Returns:
      The Signatures in form of array of List of byte[]s.
    • verify

      public boolean verify​(InputStream data, InputStream signature) throws InvalidKeyException, SignatureException, IOException
      Verify the given signature, meaning that it was created from the given data with the publicKey stored in the KeyManager. The parameters must be given as {link InputStream InputStreams}. An InputStream can be generated e.g. from an byte[] with ByteArrayInputStream or a File with FileInputStream. If the data was signed with an external key, the static verify or verify(InputStream data, InputStream signature, InputStream certificatePEM) methods can be used.

      Using the InputStream will leave it empty after verifying is completed.

      Verifying a signature with this method would look like this:

       
       ...
       String pathToFile = ...;
       byte[] signature = ...;
       signer.verify(new FileInputStream(pathToFile), new ByteArrayInputStream(signature));
       
       
      Parameters:
      data - The data that is assumed to be signed with the given publicKey.
      signature - The signature that should be verified.
      Returns:
      True, if the signature is valid, false otherwise.
      Throws:
      SignatureException - if the given signature's format is invalid.
      InvalidKeyException - if the public key managed by the EasySigner is not valid.
      IOException - if no data from one of the given InputStreams can be read.
    • verify

      public boolean verify​(byte[] data, byte[] signature) throws InvalidKeyException, SignatureException
      Verify the given signature, meaning that it was created from the given data with the publicKey stored in the KeyManager. The parameters must be given as byte[].

      Verifying a signature with this method would look like this:

       
       ...
       byte[] messageToVerify = ...;
       byte[] signature = ...;
       signer.verify(messageToVerify, signature);
       
       
      Parameters:
      data - The data that is assumed to be signed with the given publicKey.
      signature - The signature that should be verified.
      Returns:
      True, if the signature is valid, false otherwise.
      Throws:
      SignatureException - if the given signature's format is invalid.
      InvalidKeyException - if the public key managed by the EasySigner is not valid.
    • verify

      public static boolean verify​(byte[] data, byte[] signature, PublicKey publicKey) throws InvalidKeyException, SignatureException, IllegalArgumentException
      Verify the given signature, meaning that it was created with the given publicKey from the given data. This method is static and can be used without initializing an instance of EasySigner.

      Verifying a signature with this method would look like this:

       
       ...
       String toBeSigned = ...;
       byte[] signature = ...;
       PublicKey publicKey = ...;
       signer.verify(toBeSigned.getBytes(), signature, publicKey);
       
       
      Parameters:
      data - The data that is assumed to be signed with the given publicKey.
      signature - The signature that should be verified.
      publicKey - The public key corresponding to the private key that was used to sign the given data.
      Returns:
      True, if the signature is valid, false otherwise.
      Throws:
      InvalidKeyException - if the given public key is not valid.
      SignatureException - if the given signature's format is invalid.
      IllegalArgumentException - if one of the given signature is null.
    • verify

      public static boolean verify​(InputStream data, InputStream signature, InputStream certificatePEM) throws CertificateException, InvalidKeyException, SignatureException, IOException
      Verify the given signature, meaning that it was created with the given publicKey from the given data. The parameters data and signature have to be given as {link InputStream InputStreams}. An InputStream can be generated e.g. from an byte[] with ByteArrayInputStream or a File with FileInputStream. This method is static and can be used without initializing an instance of EasySigner.

      Using the InputStream will leave it empty after verifying is completed.

      Verifying a signature with this method would look like this:

       
       ...
       String filePath = ...;
       byte[] signature = ...;
       String certificatePath = ...;
       signer.verify(new FileInputStream(filePath), new ByteArrayInputStream(signature), new FileInputStream(certificatePath));
       
       
      Parameters:
      data - The data that is assumed to be signed with the given publicKey.
      signature - The signature that should be verified.
      certificatePEM - The certificate formatted as PEM containing the public key corresponding to the private key that was used to sign the data.
      Returns:
      True, if the signature is valid, false otherwise.
      Throws:
      CertificateException - if the given certificate is not valid.
      InvalidKeyException - if the certificate contains an invalid public key.
      SignatureException - if the given signature's format is invalid.
      IllegalArgumentException - if one of the given signature is null.
      IOException - if no data from one of the given InputStreams can be read.
    • verify

      public static boolean verify​(InputStream data, InputStream signature, PublicKey publicKey) throws InvalidKeyException, SignatureException, IllegalArgumentException, IOException
      Verify the given signature, meaning that it was created with the given publicKey from the given data. The parameters data and signature have to be given as {link InputStream InputStreams}. An InputStream can be generated e.g. from an byte[] with ByteArrayInputStream or a File with FileInputStream. This method is static and can be used without initializing an instance of EasySigner.

      Using the InputStream will leave it empty after verifying is completed.

      Verifying a signature with this method would look like this:

       
       ...
       String filePath = ...;
       byte[] signature = ...;
       PublicKey publicKey = ...;
       signer.verify(new FileInputStream(filePath), new ByteArrayInputStream(signature), publicKey);
       
       
      Parameters:
      data - The data that is assumed to be signed with the given publicKey.
      signature - The signature that should be verified.
      publicKey - The public key corresponding to the private key that was used to sign the given data.
      Returns:
      True, if the signature is valid, false otherwise.
      Throws:
      InvalidKeyException - if the certificate contains an invalid public key.
      SignatureException - if the given signature's format is invalid.
      IllegalArgumentException - if one of the given signature is null.
      IOException - if no data from one of the given InputStreams can be read.
    • getPublicKey

      public PublicKey getPublicKey()
      Get the PublicKey from the KeyManager.
      Returns:
      The PublicKey.
    • getCertificate

      public Certificate getCertificate()
      Get the Certificate from the KeyManager.
      Returns:
      The Certificate.
    • getKeyManager

      public KeyManager getKeyManager()
      Get the KeyManager
      Returns:
      The KeyManager.
    • setHashAlgorithm

      public void setHashAlgorithm​(String hashAlgorithm)
      Sets the hash algorithm used when creating a signature (the given data is first hashed with this algorithm and then signed). Possible algorithms are SHA256 and SHA512.
      Parameters:
      hashAlgorithm - The hash algorithm to be used for signing.