public class YAACKeyManager
extends java.lang.Object
implements javax.net.ssl.X509KeyManager
This class is the repository for keys used for this signing and verifying, backed by a Java keystore. It supports:
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
Modifier and Type | Class and Description |
---|---|
static class |
YAACKeyManager.KeyType
Enumeration identifying different types of encryption keys that can be stored in the
KeyManager.
|
Modifier and Type | Method and Description |
---|---|
java.lang.String |
chooseClientAlias(java.lang.String[] keyTypes,
java.security.Principal[] principals,
java.net.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).
|
java.lang.String |
chooseServerAlias(java.lang.String algChoice,
java.security.Principal[] principals,
java.net.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).
|
void |
createSecretKey(java.lang.String alias)
Create a new secret (symmetric) key.
|
void |
deleteKey(java.lang.String alias)
Delete a key from the local keystore.
|
boolean |
doesKeystoreExistYet()
Test if the keystore has been created yet,
|
java.lang.String[] |
findMatchingKeys(java.lang.String callsign,
YAACKeyManager.KeyType keyType)
Search the keystore for keys that match the destination addressee of the specified message.
|
java.lang.String[] |
getAliases()
Get all key aliases stored in the keystore.
|
java.lang.String[] |
getAssociations(java.lang.String alias)
Get all the associated callsigns allowed to use the key specified by the alias.
|
java.security.cert.X509Certificate[] |
getCertificateChain(java.lang.String alias)
Returns the certificate chain associated with the given alias.
|
java.lang.String[] |
getClientAliases(java.lang.String algChoice,
java.security.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).
|
static YAACKeyManager |
getInstance()
Get the KeyManager singleton.
|
java.security.Key |
getKey(java.lang.String alias)
Get the key associated with the specified alias.
|
YAACKeyManager.KeyType |
getKeyType(java.lang.String alias)
Get the type of key associated with the specified alias.
|
java.security.PrivateKey |
getPrivateKey(java.lang.String alias)
Get the PrivateKey associated with the specified alias.
|
java.lang.String[] |
getServerAliases(java.lang.String algChoice,
java.security.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).
|
void |
insertPrivateKey(java.lang.String alias,
java.security.PrivateKey key,
java.security.cert.Certificate[] certs)
Insert a private key with its associated public key certificate chain.
|
void |
insertPublicCertificateChain(java.lang.String alias,
java.security.cert.CertPath chain)
Store the public key certificates for some other station into the keystore.
|
void |
insertSecretKey(java.lang.String alias,
byte[] encoded)
Store a byte-encoded secret (symmetric) key in the keystore.
|
boolean |
isPasswordSet()
Test if the backing keystore's password has been set.
|
static void |
main(java.lang.String[] args)
unit test.
|
void |
setAssociations(java.lang.String alias,
java.lang.String[] associations)
Get all the associated callsigns allowed to use the key specified by the alias.
|
void |
setPassword(char[] password)
Set the password to be used to decode keys in the backing keystore.
|
void |
sign(AprsSignableMessage mm,
java.lang.String alias)
Sign a timestamped APRS message with the specified key.
|
SignableMessage.SignatureState |
verify(AprsSignableMessage mm)
Verify the signature (if any) in an APRS message against the keys in the local keystore.
|
public static YAACKeyManager getInstance()
public boolean isPasswordSet()
public void setPassword(char[] password) throws java.lang.NullPointerException, java.io.IOException, java.security.GeneralSecurityException
password
- char array of the passwordjava.lang.NullPointerException
- if password was nulljava.io.IOException
- if keystore file could not be read for any reasonjava.security.GeneralSecurityException
- if keystore file could not be decoded for any reasonpublic boolean doesKeystoreExistYet()
public java.security.Key getKey(java.lang.String alias) throws java.lang.NullPointerException
alias
- String alias name for a keyjava.lang.NullPointerException
- if the keystore's password was not successfully set yetpublic java.lang.String[] getAliases() throws java.lang.NullPointerException
java.lang.NullPointerException
- if the keystore's password was not successfully set yetpublic YAACKeyManager.KeyType getKeyType(java.lang.String alias) throws java.lang.NullPointerException
alias
- String name associated with the desired keyjava.lang.NullPointerException
- if the keystore's password was not successfully set yetpublic java.lang.String[] getAssociations(java.lang.String alias)
alias
- String name of the key to querypublic void setAssociations(java.lang.String alias, java.lang.String[] associations)
alias
- String name of the key to modifyassociations
- array of callsign Strings to associate with named keypublic void createSecretKey(java.lang.String alias) throws java.lang.NullPointerException, java.security.KeyStoreException
alias
- String name to label the keyjava.lang.NullPointerException
- if keystore password hasn't been correctly set yetjava.security.KeyStoreException
- if key can't be stored in backing keystore filepublic void insertSecretKey(java.lang.String alias, byte[] encoded) throws java.lang.NullPointerException, java.security.KeyStoreException
alias
- String name to associate with keyencoded
- byte array of the encoded keyjava.lang.NullPointerException
- if keystore password hasn't been correctly set yetjava.security.KeyStoreException
- if key can't be stored in backing keystore filepublic void insertPublicCertificateChain(java.lang.String alias, java.security.cert.CertPath chain)
alias
- String name to associate with this public keychain
- array of Certificates containing the public key and identifying the issuers up to
the certificate authoritypublic void insertPrivateKey(java.lang.String alias, java.security.PrivateKey key, java.security.cert.Certificate[] certs) throws java.security.KeyStoreException
alias
- String name to associate with this key pairkey
- PrivateKeycerts
- array of Certificates listing the public key associated with the private key and the
issuers up to the certificate authorityjava.security.KeyStoreException
- if the key pair could not be storedpublic void deleteKey(java.lang.String alias) throws java.security.KeyStoreException, java.io.IOException
alias
- String name of the keyjava.security.KeyStoreException
- if the keystore can't be modifiedjava.io.IOException
- if the altered keystore can't be checkpointed to the backing disk filepublic java.lang.String[] findMatchingKeys(java.lang.String callsign, YAACKeyManager.KeyType keyType)
callsign
- String callsign to be matched against the known keyskeyType
- KeyType of keys to be searched for, or null to search for all typespublic void sign(AprsSignableMessage mm, java.lang.String alias) throws java.lang.NullPointerException, java.lang.IllegalStateException, java.lang.IllegalArgumentException, java.security.GeneralSecurityException
mm
- MessageMessage to signalias
- String name of key to use for signaturejava.lang.NullPointerException
- if keystore password hasn't been correctly set yetjava.lang.IllegalStateException
- if message has already been signedjava.lang.IllegalArgumentException
- if no such key for specified aliasjava.security.GeneralSecurityException
- if key does not exist or signature algorithm doesn't work or isn't availablepublic SignableMessage.SignatureState verify(AprsSignableMessage mm) throws java.security.GeneralSecurityException
mm
- MessageMessage to verifyjava.security.GeneralSecurityException
- if key does not exist or signature algorithm doesn't work or isn't availablepublic static void main(java.lang.String[] args) throws java.lang.Exception
args
- String array, [0] = password, [1] = alias to use for testjava.lang.Exception
- if test failspublic java.lang.String chooseClientAlias(java.lang.String[] keyTypes, java.security.Principal[] principals, java.net.Socket socket)
chooseClientAlias
in interface javax.net.ssl.X509KeyManager
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.public java.lang.String[] getClientAliases(java.lang.String algChoice, java.security.Principal[] principals)
getClientAliases
in interface javax.net.ssl.X509KeyManager
algChoice
- the key algorithm type nameprincipals
- the list of acceptable CA issuer subject names, or null if it does not matter which issuers are used.public java.lang.String[] getServerAliases(java.lang.String algChoice, java.security.Principal[] principals)
getServerAliases
in interface javax.net.ssl.X509KeyManager
algChoice
- the key algorithm type nameprincipals
- the list of acceptable CA issuer subject names or null if it does not matter which issuers are used.public java.lang.String chooseServerAlias(java.lang.String algChoice, java.security.Principal[] principals, java.net.Socket socket)
chooseServerAlias
in interface javax.net.ssl.X509KeyManager
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.public java.security.cert.X509Certificate[] getCertificateChain(java.lang.String alias)
getCertificateChain
in interface javax.net.ssl.X509KeyManager
alias
- the alias namepublic java.security.PrivateKey getPrivateKey(java.lang.String alias) throws java.lang.NullPointerException
getPrivateKey
in interface javax.net.ssl.X509KeyManager
alias
- String name of key to look upjava.lang.NullPointerException
- if the keystore has not been opened yet