Class YAACKeyManager

java.lang.Object
org.ka2ddo.yaac.auth.YAACKeyManager
All Implemented Interfaces:
KeyManager, X509KeyManager

public class YAACKeyManager extends Object implements X509KeyManager
This class stores encryption keys used for signing and verifying messages. There are two meanings of signing:
  1. public key signing with the sender's private key and verifying with their public key.
  2. secret key Hashed Message Authentication Code for signing and verifying.

This class is the repository for keys used for this signing and verifying, backed by a Java keystore. It supports:

  1. private keys with associated public key certificate chains,
  2. public key certificates of other users,
  3. secret keys of the local user or other users.
The keys stored in the keystore are associated with lists of sending station ID's and broadcast (bulletin) addressees.

It also provides the APRS message signing and verifying logic, and provides a means to associate other station's callsigns with keys and certificates. This class also provides services to create, export, import, and delete keys and certificates.

This is based on research reported by Bryan Hoyer KG6GEU in a presentation to the NW Digital Radio group on 2013-Mar-31

Author:
Andrew Pavlin, KA2DDO
  • Method Details

    • getInstance

      public static YAACKeyManager getInstance()
      Get the KeyManager singleton.
      Returns:
      instance of KeyManager
    • isPasswordSet

      public boolean isPasswordSet()
      Test if the backing keystore's password has been set.
      Returns:
      boolean true if password has been successfully set
    • setPassword

      public void setPassword(char[] password) throws NullPointerException, IOException, GeneralSecurityException
      Set the password to be used to decode keys in the backing keystore.
      Parameters:
      password - char array of the password
      Throws:
      NullPointerException - if password was null
      IOException - if keystore file could not be read for any reason
      GeneralSecurityException - if keystore file could not be decoded for any reason
    • doesKeystoreExistYet

      public boolean doesKeystoreExistYet()
      Test if the keystore has been created yet,
      Returns:
      boolean true if keystore backing file exists (i.e., the keystore has been created)
    • getKey

      public Key getKey(String alias) throws NullPointerException
      Get the key associated with the specified alias.
      Parameters:
      alias - String alias name for a key
      Returns:
      the Key associated with the alias
      Throws:
      NullPointerException - if the keystore's password was not successfully set yet
    • getAliases

      public String[] getAliases() throws NullPointerException
      Get all key aliases stored in the keystore.
      Returns:
      array of String aliases
      Throws:
      NullPointerException - if the keystore's password was not successfully set yet
    • getKeyType

      public YAACKeyManager.KeyType getKeyType(String alias) throws NullPointerException
      Get the type of key associated with the specified alias.
      Parameters:
      alias - String name associated with the desired key
      Returns:
      KeyType specifying the kind of key associated with the alias, or null if no key with the specified alias
      Throws:
      NullPointerException - if the keystore's password was not successfully set yet
    • getAssociations

      public String[] getAssociations(String alias)
      Get all the associated callsigns allowed to use the key specified by the alias.
      Parameters:
      alias - String name of the key to query
      Returns:
      array of callsigns and broadcast aliases associated with the named key (possibly zero length if no associations)
    • setAssociations

      public void setAssociations(String alias, String[] associations)
      Get all the associated callsigns allowed to use the key specified by the alias.
      Parameters:
      alias - String name of the key to modify
      associations - array of callsign Strings to associate with named key
    • createSecretKey

      public void createSecretKey(String alias) throws NullPointerException, KeyStoreException
      Create a new secret (symmetric) key.
      Parameters:
      alias - String name to label the key
      Throws:
      NullPointerException - if keystore password hasn't been correctly set yet
      KeyStoreException - if key can't be stored in backing keystore file
    • insertSecretKey

      public void insertSecretKey(String alias, byte[] encoded) throws NullPointerException, KeyStoreException
      Store a byte-encoded secret (symmetric) key in the keystore. Used to import a key generated by someone else.
      Parameters:
      alias - String name to associate with key
      encoded - byte array of the encoded key
      Throws:
      NullPointerException - if keystore password hasn't been correctly set yet
      KeyStoreException - if key can't be stored in backing keystore file
    • insertPublicCertificateChain

      public void insertPublicCertificateChain(String alias, CertPath chain)
      Store the public key certificates for some other station into the keystore.
      Parameters:
      alias - String name to associate with this public key
      chain - array of Certificates containing the public key and identifying the issuers up to the certificate authority
    • insertPrivateKey

      public void insertPrivateKey(String alias, PrivateKey key, Certificate[] certs) throws KeyStoreException
      Insert a private key with its associated public key certificate chain.
      Parameters:
      alias - String name to associate with this key pair
      key - PrivateKey
      certs - array of Certificates listing the public key associated with the private key and the issuers up to the certificate authority
      Throws:
      KeyStoreException - if the key pair could not be stored
    • deleteKey

      public void deleteKey(String alias) throws KeyStoreException, IOException
      Delete a key from the local keystore.
      Parameters:
      alias - String name of the key
      Throws:
      KeyStoreException - if the keystore can't be modified
      IOException - if the altered keystore can't be checkpointed to the backing disk file
    • findMatchingKeys

      public String[] findMatchingKeys(String callsign, YAACKeyManager.KeyType keyType)
      Search the keystore for keys that match the destination addressee of the specified message.
      Parameters:
      callsign - String callsign to be matched against the known keys
      keyType - KeyType of keys to be searched for, or null to search for all types
      Returns:
      array of String names of keys that are associated with the specified callsign string (may be zero-length if no matches)
    • sign

      Sign a timestamped APRS message with the specified key.
      Parameters:
      mm - MessageMessage to sign
      alias - String name of key to use for signature
      Throws:
      NullPointerException - if keystore password hasn't been correctly set yet
      IllegalStateException - if message has already been signed
      IllegalArgumentException - if no such key for specified alias
      GeneralSecurityException - if key does not exist or signature algorithm doesn't work or isn't available
    • verify

      Verify the signature (if any) in an APRS message against the keys in the local keystore.
      Parameters:
      mm - MessageMessage to verify
      Returns:
      SignatureState of the message
      Throws:
      GeneralSecurityException - if key does not exist or signature algorithm doesn't work or isn't available
    • main

      public static void main(String[] args) throws Exception
      unit test.
      Parameters:
      args - String array, [0] = password, [1] = alias to use for test
      Throws:
      Exception - if test fails
    • chooseClientAlias

      public String chooseClientAlias(String[] keyTypes, Principal[] principals, Socket socket)
      Choose an alias to authenticate the client side of a secure socket given the public key type and the list of certificate issuer authorities recognized by the peer (if any).
      Specified by:
      chooseClientAlias in interface X509KeyManager
      Parameters:
      keyTypes - the key algorithm type name(s), ordered with the most-preferred key type first.
      principals - the list of acceptable CA issuer subject names or null if it does not matter which issuers are used.
      socket - he socket to be used for this connection. This parameter can be null, which indicates that implementations are free to select an alias applicable to any socket.
      Returns:
      the alias name for the desired key, or null if there are no matches
    • getClientAliases

      public String[] getClientAliases(String algChoice, Principal[] principals)
      Get the matching aliases for authenticating the client side of a secure socket given the public key type and the list of certificate issuer authorities recognized by the peer (if any).
      Specified by:
      getClientAliases in interface X509KeyManager
      Parameters:
      algChoice - the key algorithm type name
      principals - the list of acceptable CA issuer subject names, or null if it does not matter which issuers are used.
      Returns:
      an array of the matching alias names, or null if there were no matches.
    • getServerAliases

      public String[] getServerAliases(String algChoice, Principal[] principals)
      Get the matching aliases for authenticating the server side of a secure socket given the public key type and the list of certificate issuer authorities recognized by the peer (if any).
      Specified by:
      getServerAliases in interface X509KeyManager
      Parameters:
      algChoice - the key algorithm type name
      principals - the list of acceptable CA issuer subject names or null if it does not matter which issuers are used.
      Returns:
      an array of the matching alias names, or null if there were no matches.
    • chooseServerAlias

      public String chooseServerAlias(String algChoice, Principal[] principals, Socket socket)
      Choose an alias to authenticate the server side of a secure socket given the public key type and the list of certificate issuer authorities recognized by the peer (if any).
      Specified by:
      chooseServerAlias in interface X509KeyManager
      Parameters:
      algChoice - the key algorithm type name.
      principals - the list of acceptable CA issuer subject names or null if it does not matter which issuers are used.
      socket - the socket to be used for this connection. This parameter can be null, which indicates that implementations are free to select an alias applicable to any socket.
      Returns:
      the alias name for the desired key, or null if there are no matches.
    • getCertificateChain

      public X509Certificate[] getCertificateChain(String alias)
      Returns the certificate chain associated with the given alias.
      Specified by:
      getCertificateChain in interface X509KeyManager
      Parameters:
      alias - the alias name
      Returns:
      the certificate chain (ordered with the user's certificate first and the root certificate authority last), or null if the alias can't be found.
    • getPrivateKey

      public PrivateKey getPrivateKey(String alias) throws NullPointerException
      Get the PrivateKey associated with the specified alias.
      Specified by:
      getPrivateKey in interface X509KeyManager
      Parameters:
      alias - String name of key to look up
      Returns:
      PrivateKey for the alias, or null if no such key
      Throws:
      NullPointerException - if the keystore has not been opened yet