<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div>We're starting some early field testing of the Trsst Project, and while we're still in need of a security review and models and documentation to support it, I wanted to get some feedback on the encryption piece.</div><div><br></div><div>Background: </div><div><br></div><div>Trsst is a convention for using Atom and the Atom Publishing Protocol with XML-Signatures and XML-Encryption as a foundation for building interoperable microblogging services (think: open replacements for Twitter/Facebook) that support decentralized account creation (just generate a keypair), and signed and optionally encrypted public entries.  FAQ is here: <a href="https://github.com/TrsstProject/trsst/wiki/Frequently-Asked-Questions">https://github.com/TrsstProject/trsst/wiki/Frequently-Asked-Questions</a> </div><div><br></div><div>For a private message, we generate a random 256-bit key and encrypt with AES.  Then for each recipient, we use a hash of the shared ECDH secret and the message-id to encrypt the key and append it to the message.  All public keys are static, and all public and private messages are viewable by anyone.  </div><div><br></div><div>Specific questions:</div><div><br></div><div>(1) An account is permanently associated with one EC keypair for signing, and another optional keypair for encryption which can changed but probably not often if ever.  How much of a problem would it be to use the same permanent keypair for both signing and encryption?  Moving/copying your content to a new account is the recourse for a lost or compromised key, and isn't terribly costly.</div><div><br></div><div>(2) Private messages are not always addressed outside the encryption envelope.  If unaddressed, you have to try each of the keys on a message to see if it is intended for you, which is why we hash the key.  Could the pattern of first half of the encrypted data always being a random key and the second half always being a hash of that key be exploited?  </div><div><br></div><div>(3) To ensure you can decrypt your own message, you encode one of the keys for yourself.  Might your private key be compromised when used with your own public key moreso than someone else's public key?</div><div><br></div><div>The relevant implementation in Java using Bouncy Castle is below.  The rest of the source is at: <a href="https://github.com/TrsstProject/trsst">https://github.com/TrsstProject/trsst</a></div><div><br></div><div>Many thanks for pointing out issues and errors, glaring or otherwise.</div><div><br></div><div>  - Michael</div><div><br></div><div>-----</div><div><br></div><div><div style="margin: 0px; "><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; ">/**</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "> * Takes the specified 32 bytes, appends its sha-256 digest, and xor</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "> * encrypts those 64 bytes with the sha-512 hash of the ECDH shared secret</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "> * and the entry id.</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "> * </span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "> * @param input 32 byte key to be encrypted</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "> * @param publicKey</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "> * @param privateKey</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "> * @return</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "> * @throws SecurityException if unexpected error</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "> */</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; ">public static byte[] encryptKeyWithECDH(byte[] input, long entryId,</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">            </span>PublicKey publicKey, PrivateKey privateKey)</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">         </span>throws SecurityException {</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">  </span>assert input.length == 32; // 256 bit key</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">   </span>byte[] result = null;</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">       </span>try {</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">               </span>KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH", "BC");</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">             </span>keyAgreement.init(privateKey);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">              </span>keyAgreement.doPhase(publicKey, true);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">              </span>byte[] sharedSecret = keyAgreement.generateSecret();</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><br></span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">         </span>// generate 512 bits using shared secret and entry id</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">               </span>MessageDigest sha512 = MessageDigest.getInstance("SHA-512");</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">              </span>sha512.update(sharedSecret);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">                </span>sha512.update(ByteBuffer.allocate(8).putLong(entryId));</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">             </span>byte[] sharedHash = sha512.digest();</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><br></span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">         </span>// calculate a digest of the input</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">          </span>byte[] digest = MessageDigest.getInstance("SHA-256").digest(input);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><br></span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">                </span>// xor the key and the digest against the shared hash</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">               </span>int i;</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">              </span>result = new byte[64];</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">              </span>for (i = 0; i < 32; i++) {</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">                       </span>result[i] = (byte) (input[i] ^ sharedHash[i]);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">              </span>}</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">           </span>for (i = 0; i < 32; i++) {</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">                       </span>result[i + 32] = (byte) (digest[i] ^ sharedHash[i + 32]);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">           </span>}</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">   </span>} catch (Exception e) {</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">             </span>log.error("Error while encrypting element", e);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">           </span>throw new SecurityException(e);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">     </span>}</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">   </span>return result;</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; ">}</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><br></span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; ">/**</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "> * Takes the specified 64 byte encoded input and xor decrypts it with the</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "> * sha-512 hash of the ECDH shared secret and the entry id. Then checks to</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "> * see if the last 32 bytes is the sha-256 hash of the first 32 bytes. If</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "> * so, returns the first 32 bytes of the decrypted content. Otherwise, then</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "> * this key was not intended for us, and returns null.</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "> * </span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "> * @param input 64 byte input to be decrypted</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "> * @param publicKey</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "> * @param privateKey</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "> * @return the original 32 byte input, or null if unintended recipient.</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "> * @throws SecurityException if unexpected error</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "> */</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; ">public static byte[] decryptKeyWithECDH(byte[] input, long entryId,</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">              </span>PublicKey publicKey, PrivateKey privateKey)</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">         </span>throws SecurityException {</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">  </span>assert input.length == 64; // 512 bit encrypted key</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; "> </span>try {</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">               </span>KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH", "BC");</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">             </span>keyAgreement.init(privateKey);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">              </span>keyAgreement.doPhase(publicKey, true);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">              </span>byte[] sharedSecret = keyAgreement.generateSecret();</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><br></span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">         </span>// generate 512 bits using shared secret and entry id</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">               </span>MessageDigest sha512 = MessageDigest.getInstance("SHA-512");</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">              </span>sha512.update(sharedSecret);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">                </span>sha512.update(ByteBuffer.allocate(8).putLong(entryId));</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">             </span>byte[] sharedHash = sha512.digest();</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><br></span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">         </span>// xor the key and the digest against the shared hash</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">               </span>int i;</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">              </span>byte[] decoded = new byte[64];</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">              </span>for (i = 0; i < 64; i++) {</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">                       </span>decoded[i] = (byte) (input[i] ^ sharedHash[i]);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">             </span>}</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><br></span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">            </span>// calculate digest of the decoded key</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">              </span>MessageDigest sha256 = MessageDigest.getInstance("SHA-256");</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">              </span>sha256.update(decoded, 0, 32);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">              </span>byte[] digest = sha256.digest();</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><br></span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">             </span>// verify that the digest of first 32 bytes matches last 32 bytes</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">           </span>for (i = 0; i < 32; i++) {</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">                       </span>if (digest[i] != decoded[i + 32]) {</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">                         </span>// incorrectly decoded: we're not the intended recipient</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">                            </span>return null;</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">                        </span>}</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">           </span>}</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">           </span>return Arrays.copyOfRange(decoded, 0, 32);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">  </span>} catch (Exception e) {</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">             </span>log.error("Error while decrypting element", e);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">           </span>throw new SecurityException(e);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">     </span>}</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; ">}</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><br></span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; ">public static byte[] generateAESKey() {</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">  </span>byte[] result = new byte[32];</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">       </span>new SecureRandom().nextBytes(result);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">       </span>return result;</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; ">}</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><br></span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; ">public static byte[] encryptAES(byte[] input, byte[] key)</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">           </span>throws InvalidCipherTextException {</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; "> </span>return _cryptBytesAES(input, key, true);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; ">}</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><br></span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; ">public static byte[] decryptAES(byte[] input, byte[] key)</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">         </span>throws InvalidCipherTextException {</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; "> </span>return _cryptBytesAES(input, key, false);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; ">}</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><br></span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; ">private static byte[] _cryptBytesAES(byte[] input, byte[] key,</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">           </span>boolean forEncryption) throws InvalidCipherTextException {</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">  </span>assert key.length == 32; // 32 bytes == 256 bits</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">    </span>CipherParameters cipherParameters = new KeyParameter(key);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">  </span>BlockCipher blockCipher = new AESEngine();</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">  </span>BlockCipherPadding blockCipherPadding = new ZeroBytePadding();</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">      </span>BufferedBlockCipher bufferedBlockCipher = new PaddedBufferedBlockCipher(</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">                    </span>blockCipher, blockCipherPadding);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">   </span>return process(input, bufferedBlockCipher, cipherParameters,</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">                        </span>forEncryption);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; ">}</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><br></span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; ">private static byte[] process(byte[] input,</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">                </span>BufferedBlockCipher bufferedBlockCipher,</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">            </span>CipherParameters cipherParameters, boolean forEncryption)</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">           </span>throws InvalidCipherTextException {</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; "> </span>bufferedBlockCipher.init(forEncryption, cipherParameters);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><br></span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">   </span>int inputOffset = 0;</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">        </span>int inputLength = input.length;</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><br></span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">      </span>int maximumOutputLength = bufferedBlockCipher</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">                       </span>.getOutputSize(inputLength);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">        </span>byte[] output = new byte[maximumOutputLength];</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">      </span>int outputOffset = 0;</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">       </span>int outputLength = 0;</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><br></span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">        </span>int bytesProcessed;</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><br></span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">  </span>bytesProcessed = bufferedBlockCipher.processBytes(input, inputOffset,</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">                       </span>inputLength, output, outputOffset);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; "> </span>outputOffset += bytesProcessed;</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">     </span>outputLength += bytesProcessed;</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><br></span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">      </span>bytesProcessed = bufferedBlockCipher.doFinal(output, outputOffset);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; "> </span>outputOffset += bytesProcessed;</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">     </span>outputLength += bytesProcessed;</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><br></span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">      </span>if (outputLength == output.length) {</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">                </span>return output;</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">      </span>} else {</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">            </span>byte[] truncatedOutput = new byte[outputLength];</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">            </span>System.arraycopy(output, 0, truncatedOutput, 0, outputLength);</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">              </span>return truncatedOutput;</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; "><span class="Apple-tab-span" style="white-space: pre; ">     </span>}</span></font></div><div style="margin: 0px; "><font face="Monaco"><span style="font-size: 11px; ">}</span></font></div><div><font face="Monaco"><span style="font-size: 11px; "><br></span></font></div></div></div></body></html>