Implements public part of the asymmetric cipher (with public key) used to send encrypted local secret key (used for symmetric ciphering of peer-to-peer datagram packets) to remote peer. More...
Public Member Functions | |
PublicEncryptor (String serializedPublicKey, String remoteUserId) | |
Deserializes public key from the Base64 string and instantiates PublicEncryptor. | |
boolean | isActive () |
Returns if cipher is properly initialized. | |
boolean | isVerified () |
Returns if public key was verified. | |
String | getVerificatorName () |
Returns if name of the verificator from authorized keys that verified this public key. | |
byte[] | encrypt (byte[] plainText) |
Encrypts plain text using public key. | |
String | encryptAndSerialize (Serializable object) |
Returns Base64 of encrypted (using our public key) object. | |
Static Public Member Functions | |
static void | loadAuthorizedPublicKeys () |
Loads authorized keys. | |
static String | verifyObject (SignedObject object) |
Verifies signed object with a public key from the authorized public keys. | |
Static Private Member Functions | |
static void | createEmptyAuthorizedPublicKeys (String filename) |
Create empty authorized keys file if it does not exist and adjust permissions. | |
Private Attributes | |
PublicKey | publicKey = null |
Public key. | |
Cipher | cipher = null |
Instance of the encrypting engine based on remote public key. | |
String | serializedPublicKey = null |
Remote public key: serialized and encoded as Base64 string. | |
String | verificator = null |
Contains name of the verificator (i.e the name associated with authorized public key that has verified this public key). | |
Static Private Attributes | |
static final String | padding = "/ECB/PKCS1PADDING" |
Padding to be used when ciphering/deciphering JCE does not support RSA/CBC so the CBC mode is built on the top of ECB in PublicEncryptor.encrypt(). | |
static final String | digest = "SHA1" |
Message digest used for creating/validating signatures. | |
static final String | authorizedKeysFile = "mykf-authorized-keys.txt" |
The name of the file holding authorized public keys of remote peers. | |
static ArrayList< NamedPublicKey > | authorizedKeys = null |
Authorized public keys (loaded from file) |
Implements public part of the asymmetric cipher (with public key) used to send encrypted local secret key (used for symmetric ciphering of peer-to-peer datagram packets) to remote peer.
The class holds also list of authorized public keys, which is used to verify signed objects received from peers.
Definition at line 34 of file PublicEncryptor.java.
crypto.PublicEncryptor.PublicEncryptor | ( | String | serializedPublicKey, |
String | remoteUserId | ||
) |
Deserializes public key from the Base64 string and instantiates PublicEncryptor.
Verifies public key with the public key retrieved from the authorized keys.
Definition at line 84 of file PublicEncryptor.java.
References crypto.PublicEncryptor.cipher, crypto.PublicEncryptor.padding, crypto.PublicEncryptor.publicKey, crypto.PublicEncryptor.serializedPublicKey, crypto.PublicEncryptor.verificator, and crypto.PublicEncryptor.verifyObject().
{ /* Deserialize and verify public key used for encryption. */ this.serializedPublicKey = serializedPublicKey; try { Object object = Base64.decodeToObject( this.serializedPublicKey ); SignedObject signedObject = null; if ( object instanceof SignedObject ) { signedObject = (SignedObject) object; this.verificator = PublicEncryptor.verifyObject( signedObject ); object = signedObject.getObject (); } if ( object instanceof PublicKey ) { this.publicKey = (PublicKey)object; String algorithm = this.publicKey.getAlgorithm (); this.cipher = Cipher.getInstance( algorithm + padding ); } } catch( ClassNotFoundException e ) { Log.exception( Log.WARN, e ); } catch( NoSuchAlgorithmException e ) { Log.exception( Log.WARN, e ); } catch( NoSuchPaddingException e ) { Log.exception( Log.WARN, e ); } catch( IOException e ) { Log.exception( Log.WARN, e ); } /* If failed to create serializedPublicKey, then fail for good. */ if ( this.publicKey == null ) { this.cipher = null; } }
static void crypto.PublicEncryptor.createEmptyAuthorizedPublicKeys | ( | String | filename ) | [static, private] |
Create empty authorized keys file if it does not exist and adjust permissions.
Definition at line 138 of file PublicEncryptor.java.
Referenced by crypto.PublicEncryptor.loadAuthorizedPublicKeys().
{ try { File file = new File( filename ); if ( ! file.exists () ) { file.createNewFile (); } if ( file.exists () ) { /* Change permissions using native OS 'chmod' command (ignoring Windows), * so that no one but the owner might read its contents. */ String osName = System.getProperty( "os.name" ).toLowerCase(); if ( ! osName.matches( "^.*windows.*$" ) ) { try { Runtime.getRuntime().exec( new String[] { "chmod", "go=", filename } ); } catch( IOException e ) { Log.trace( "Failed to do chmod; OS = " + osName ); Log.exception( Log.TRACE, e ); } } } } catch( Exception e ) { Log.exception( Log.ERROR, e ); } }
byte [] crypto.PublicEncryptor.encrypt | ( | byte[] | plainText ) |
Encrypts plain text using public key.
Emulates CBC (cipher-block chaining) using plain ECB. Why? -- Because JCE does not support RSA/CBC cipher (only RSA/ECB).
See Cipher-block chaining (CBC)
Definition at line 342 of file PublicEncryptor.java.
References crypto.PublicEncryptor.cipher, and crypto.PublicEncryptor.publicKey.
Referenced by crypto.PublicEncryptor.encryptAndSerialize(), and crypto.AsymmetricCipher.sanityCheck().
{ if ( this.cipher == null ) { return null; } byte[] output = null; synchronized( this.cipher ) { try { this.cipher.init( Cipher.ENCRYPT_MODE, publicKey ); /* cipher.getBlockSize () returns always 0, so for the RSA * we can calculate block size as output size - 11 octets overhead. * e.g. 117 octets for 1024-bit RSA key size (= 1024/8 - 11 ) */ int blockSize = cipher.getOutputSize( 1 ) - 11; ByteArrayOutputStream bOut = new ByteArrayOutputStream (); byte[] xorBlock = new byte[ blockSize ]; for ( int pos = 0; pos < plainText.length; pos += blockSize ) { int len = Math.min( plainText.length - pos, blockSize ); for ( int i = 0; i < len; ++i ) { xorBlock[i] = (byte)( xorBlock[i] ^ plainText[ pos + i ] ); } byte[] cipherBlock = this.cipher.doFinal( xorBlock, 0, len ); bOut.write( cipherBlock ); System.arraycopy( cipherBlock, 0, xorBlock, 0, blockSize ); } output = bOut.toByteArray (); } catch( Exception e ) { Log.exception( Log.ERROR, e ); } } return output; }
String crypto.PublicEncryptor.encryptAndSerialize | ( | Serializable | object ) |
Returns Base64 of encrypted (using our public key) object.
Definition at line 394 of file PublicEncryptor.java.
References crypto.PublicEncryptor.encrypt().
Referenced by CryptoPhoneApp.acceptIncomingCall().
{ // TODO sign object first with our public key ! String result = null; /* Serialize instance of the secret key into secret key file */ ByteArrayOutputStream bOut = null; ObjectOutputStream oOut = null; try { bOut = new ByteArrayOutputStream (); oOut = new ObjectOutputStream( bOut ); oOut.writeObject( object ); byte[] plainText = bOut.toByteArray (); oOut.close (); bOut.close (); result = Base64.encodeBytes( encrypt( plainText ), Base64.GZIP ); } catch( Exception e ) { Log.exception( Log.ERROR, e ); } return result; }
String crypto.PublicEncryptor.getVerificatorName | ( | ) |
Returns if name of the verificator from authorized keys that verified this public key.
Definition at line 326 of file PublicEncryptor.java.
References crypto.PublicEncryptor.verificator.
Referenced by CryptoPhoneApp.deferredOnRing(), and CryptoPhoneApp.tryToVerifyInvitingCall().
{ return this.verificator; }
boolean crypto.PublicEncryptor.isActive | ( | ) |
Returns if cipher is properly initialized.
Definition at line 308 of file PublicEncryptor.java.
References crypto.PublicEncryptor.cipher.
Referenced by CryptoPhoneApp.acceptIncomingCall(), CryptoPhoneApp.deferredOnRing(), and CryptoPhoneApp.tryToVerifyInvitingCall().
{ return this.cipher != null; }
boolean crypto.PublicEncryptor.isVerified | ( | ) |
Returns if public key was verified.
Definition at line 316 of file PublicEncryptor.java.
References crypto.PublicEncryptor.verificator.
Referenced by CryptoPhoneApp.acceptIncomingCall(), CryptoPhoneApp.deferredOnRing(), and CryptoPhoneApp.tryToVerifyInvitingCall().
{ return this.verificator != null; }
static void crypto.PublicEncryptor.loadAuthorizedPublicKeys | ( | ) | [static] |
Loads authorized keys.
Definition at line 177 of file PublicEncryptor.java.
References crypto.PublicEncryptor.authorizedKeys, crypto.PublicEncryptor.authorizedKeysFile, crypto.NamedPublicKey.comment, crypto.PublicEncryptor.createEmptyAuthorizedPublicKeys(), and crypto.CipherEngine.getPrivateKeyDirectory().
Referenced by crypto.CipherEngine.initialize(), and crypto.CipherEngine.reloadAuthorizedPublicKeys().
{ StringBuffer report = new StringBuffer (); ArrayList<NamedPublicKey> newAuthKeys = new ArrayList<NamedPublicKey> (); try { String filePath = CipherEngine.getPrivateKeyDirectory () + authorizedKeysFile; createEmptyAuthorizedPublicKeys( filePath ); FileReader inf = new FileReader( filePath ); BufferedReader ins = new BufferedReader( inf ); String line; while ( ( line = ins.readLine () ) != null ) { /* Split line into 'words'; Our key should be the first word */ String[] parts = line.trim().split( "\\s{1,}" ); /* Skip empty lines */ if ( parts.length < 1 || parts[0].length () <= 0 ) { continue; } /* Skip lines starting with '#' (comments) */ if ( parts[0].equals( "#" ) ) { continue; } /* Now, deserialize public key from the first word */ String encodedKey = parts[0]; Object object = null; try { object = Base64.decodeToObject( encodedKey.toString () ); } catch( IOException e ) { Log.warn( "Failed to deserialize authorized key at line: [" + encodedKey + "]" ); Log.exception( Log.WARN, e ); } catch( ClassNotFoundException e ) { Log.warn( "Failed to deserialize authorized key at line: [" + encodedKey + "]" ); Log.exception( Log.WARN, e ); } if ( object != null && ( object instanceof NamedPublicKey ) ) { NamedPublicKey authKey = (NamedPublicKey) object; newAuthKeys.add( authKey ); if ( report.length () != 0 ) { report.append( ", " ); } report.append( authKey.comment ); } else if ( object != null ) { Log.warn( "Line: [" + encodedKey + "]" ); Log.warn( "Ignored class: " + object.getClass().toString () ); } } } catch( FileNotFoundException e ) { Log.exception( Log.TRACE, e ); } catch( IOException e ) { Log.exception( Log.WARN, e ); } if ( newAuthKeys.size() > 1 ) { report.insert( 0, "Loaded " + newAuthKeys.size() + " authorized keys: " ); Log.attn( report.toString () ); } else if ( newAuthKeys.size() == 1 ) { report.insert( 0, "Loaded authorized key: " ); Log.attn( report.toString () ); } authorizedKeys = newAuthKeys; }
static String crypto.PublicEncryptor.verifyObject | ( | SignedObject | object ) | [static] |
Verifies signed object with a public key from the authorized public keys.
Definition at line 275 of file PublicEncryptor.java.
References crypto.PublicEncryptor.authorizedKeys, crypto.PublicEncryptor.digest, and crypto.PublicEncryptor.verificator.
Referenced by crypto.AsymmetricCipher.deserializeEncryptedSecretKey(), and crypto.PublicEncryptor.PublicEncryptor().
{ if ( authorizedKeys == null ) { return null; } String verificator = null; for ( NamedPublicKey authKey : authorizedKeys ) { try { String signAlgorithm = digest + "with" + authKey.publicKey.getAlgorithm (); Signature signature = Signature.getInstance( signAlgorithm ); if ( object.verify( authKey.publicKey, signature ) ) { verificator = authKey.comment; break; } } catch( Exception e ) { /* ignore all errors; search until exhausted keys or verify succeeds */ } } return verificator; }
ArrayList<NamedPublicKey> crypto.PublicEncryptor.authorizedKeys = null [static, private] |
Authorized public keys (loaded from file)
Definition at line 56 of file PublicEncryptor.java.
Referenced by crypto.PublicEncryptor.loadAuthorizedPublicKeys(), and crypto.PublicEncryptor.verifyObject().
final String crypto.PublicEncryptor.authorizedKeysFile = "mykf-authorized-keys.txt" [static, private] |
The name of the file holding authorized public keys of remote peers.
Definition at line 51 of file PublicEncryptor.java.
Referenced by crypto.PublicEncryptor.loadAuthorizedPublicKeys().
Cipher crypto.PublicEncryptor.cipher = null [private] |
Instance of the encrypting engine based on remote public key.
Definition at line 66 of file PublicEncryptor.java.
Referenced by crypto.PublicEncryptor.encrypt(), crypto.PublicEncryptor.isActive(), and crypto.PublicEncryptor.PublicEncryptor().
final String crypto.PublicEncryptor.digest = "SHA1" [static, private] |
Message digest used for creating/validating signatures.
Definition at line 46 of file PublicEncryptor.java.
Referenced by crypto.PublicEncryptor.verifyObject().
final String crypto.PublicEncryptor.padding = "/ECB/PKCS1PADDING" [static, private] |
Padding to be used when ciphering/deciphering JCE does not support RSA/CBC so the CBC mode is built on the top of ECB in PublicEncryptor.encrypt().
Definition at line 41 of file PublicEncryptor.java.
Referenced by crypto.PublicEncryptor.PublicEncryptor().
PublicKey crypto.PublicEncryptor.publicKey = null [private] |
Public key.
Definition at line 61 of file PublicEncryptor.java.
Referenced by crypto.PublicEncryptor.encrypt(), and crypto.PublicEncryptor.PublicEncryptor().
String crypto.PublicEncryptor.serializedPublicKey = null [private] |
Remote public key: serialized and encoded as Base64 string.
Definition at line 71 of file PublicEncryptor.java.
Referenced by crypto.PublicEncryptor.PublicEncryptor().
String crypto.PublicEncryptor.verificator = null [private] |
Contains name of the verificator (i.e the name associated with authorized public key that has verified this public key).
Not null indicates that the public key was successfully verified.
Definition at line 78 of file PublicEncryptor.java.
Referenced by crypto.PublicEncryptor.getVerificatorName(), crypto.PublicEncryptor.isVerified(), crypto.PublicEncryptor.PublicEncryptor(), and crypto.PublicEncryptor.verifyObject().