package org.limewire.security.id; import java.security.InvalidAlgorithmParameterException; import java.security.PublicKey; import org.limewire.io.GUID; import org.limewire.io.InvalidDataException; /** * The SecureIdManager manages the identity of local node and * keys shared between the local node and other nodes in the network. * * When contacting another node the first time, the local node sends * the public information of the local identity to the other node and * gets back the other node's identity information. After verify the * other node's identity, the local node does Diffie-Hellman key * agreement to setup long term symmetric keys shared between these * two nodes. Those keys can be used for authentication and encryption * between them. * * See {@link SecureIdManagerImplTest#testAliceAndBobSecureCommunication()} as * an example. */ public interface SecureIdManager { /** * signature algorithm is RSA with SHA1 as message digest algorithm */ public static final String SIG_ALGO = "SHA1withRSA"; /** * signature key algorithm is RSA. */ public static final String SIG_KEY_ALGO = "RSA"; /** * signature size and signature key size are both 768 */ public static final int SIGNATURE_KEY_SIZE = 768; /** * Diffie-Hellman is the key agreement algorithm */ public static final String AGREEMENT_ALGO = "DH"; /** * Hash algorithm is MD5. * Most of bytes of the local node's GUID is the public signature key's hash value */ public static final String HASH_ALGO = "MD5"; /** * message authentication code algorithm is MD5 based hmac */ public static final String MAC_ALGO = "HmacMD5"; /** * AES cipher is used for encryption */ public static final String ENCRYPTION_KEY_ALGO = "AES"; /** * We use AES cipher, CBC mode of encryption, and PKCS5Padding as padding scheme */ public static final String ENCRYPTION_ALGO = "AES/CBC/PKCS5Padding"; /** * @return if the local node knows the remoteID and shares a key with the remote node */ public boolean isKnown(GUID remoteID); /** * @return hmac value * @throws Exception when remoteID not known */ public byte[] createHmac(GUID remoteID, byte[] data); /** * @return true if the data can be authenticated, i.e., the remoteID generated the hmac using the data. * @throws Exception when remoteID not known */ public boolean verifyHmac(GUID remoteId, byte[] data, byte[] hmacValue); /** * encrypt the plaintext. The node with remoteId is able to decrypt the * returned ciphertext. We recommend to use the bytes of message guid as * the iv. If it is not available, remoteId.byte() is fine too. * @param remoteId is the receiver's guid. * @param iv will be used to initialize the cipher. It MUST be 16 bytes long. * @return ciphertext * @throws Exception when remoteID not known * @throws InvalidAlgorithmParameterException when IV is not 16 bytes. */ public byte[] encrypt(GUID remoteId, byte[] plaintext, byte[] iv) throws InvalidAlgorithmParameterException; /** * decrypt the ciphertext sent by remoteId. The byte array of a message guid * is the recommended iv. remoteId.byte() can also be used as iv. The * application of encrypt() and decrypt() shall agree on what iv to use. * @param remoteId is the sender's guid. * @param iv will be used to initialize the cipher. It MUST be 16 bytes long. * @return plaintext * @throws Exception when remoteID not known * @throws InvalidData when the ciphertext padding is wrong * @throws InvalidAlgorithmParameterException when IV is not 16 bytes. */ public byte[] decrypt(GUID remoteId, byte[] ciphertext, byte[] iv) throws InvalidDataException, InvalidAlgorithmParameterException; /** * @return the signature */ public byte[] sign(byte[] data); /** * @return true if the data can be authenticated, * i.e., the remoteID generated the signature using the data. * @throws Exception when remoteID not known * @throws InvalidData */ public boolean verifySignature(GUID remoteId, byte[] data, byte[] signature) throws InvalidDataException; /** * @return true if the data can be authenticated, * i.e., the signature of the data can be verified with the public key. */ public boolean verifySignature(PublicKey publicKey, byte[] data, byte[] signature); /** * return the identity of the local node, including ID, signature public key, * diffie-hellman public component, and the signature on the first three fields. * the identity can be sent to other nodes on the network to setup shared keys. * @return the identity of the local node */ public Identity getLocalIdentity(); public GUID getLocalGuid(); /** * process a remote node's identity: * 1) verify the remote node's id against its signature public key * 2) verify the signature * 3) store the identity if it is not in my list * @param identity * @return true if the remote node's identity is valid based on step 1) and 2). */ public boolean addIdentity(Identity identity); }