mil.dod.th.ose.remote/src/mil/dod/th/ose/remote/api/EncryptionUtility.java
private static byte[] concatKDF(final String hashAlg, final byte[] sharedSecret, final int keyDataLen, 
          final byte[] algorithmID, final byte[] partyUInfo, final byte[] partyVInfo) 
    {
        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try 
        {
            baos.write(algorithmID);
            baos.write(partyUInfo);
            baos.write(partyVInfo);
        }
        catch (final IOException e)
        {
            throw new IllegalStateException(e);
        }
        //Each of the three fields: algorithmId, PartyUInfo and PartyVInfo shall be concatenated
        //in a fixed length sequence of substrings termed as otherInfo
        final byte[] otherInfo = baos.toByteArray();
        final byte[] key = new byte[keyDataLen];
        final MessageDigest messageDigest;
        try 
        {
            messageDigest = MessageDigest.getInstance(hashAlg);
        } 
        catch (final NoSuchAlgorithmException e) 
        {
            throw new IllegalStateException("No such hashing algorithm");
        } 
        final int hashLen = messageDigest.getDigestLength(); 
        int reps = keyDataLen / hashLen;
        if (keyDataLen % hashLen != 0)
        {
            reps = reps + 1;
        }
        for (int i = 1; i <= reps; i++)
        {
            messageDigest.update(ByteBuffer.allocate(4).putInt(i).array());//new buffer capacity is 4 bytes NOCHECKSTYLE
            messageDigest.update(sharedSecret);
            messageDigest.update(otherInfo);
            final byte[] hash = messageDigest.digest();
            if (i < reps)
            {
                System.arraycopy(hash, 0, key, hashLen * (i - 1), hashLen);
            }
            else
            {
                if (keyDataLen % hashLen == 0)
                {
                    System.arraycopy(hash, 0, key, hashLen * (i - 1), hashLen);
                }
                else
                {
                    System.arraycopy(hash, 0, key, hashLen * (i - 1), keyDataLen % hashLen);
                }
            }
        }
        return key;
    }
/**
     * NIST Concatenation Key Derivation function (KDF) per "Suite B Implementers' Guide to NIST SP 800-56A" section 5.
     * An approved Key Derivation function (KDF) shall be used to derive secret keying material from shared secret key.
     *   
     * @param hashAlg
     *      Type of hash Algorithm used. The following java.security.messagedigest API discusses several hash algorithms
     *      http://docs.oracle.com/javase/7/docs/api/java/security/MessageDigest.html
     * @param sharedSecret
     *      A shared secret key is a key that has been computed using a key agreement scheme, 
     *      in our case we use ECDH key agreement.
     * @param keyDataLen
     *      An integer that indicates the length (in bits) of the secret keying material to be generated;
     * @param algorithmID
     *      A bit string indicating how the derived keying material will be parsed
     *      and for which algorithms the derived secret keying material will be used. For e.g. AlgorithmID might 
     *      indicate that bits 1-80 are to be used as an 80-bit HMAC key and that bits 81-208 are to be used as
     *      a 128-bit AES key, This is set to (int)1 and converted to 32 bit integer value as an array of bytes.
     * @param partyUInfo
     *      A bit string containing public information that is required by the application
     *      using this KDF to be contributed by party U to the key derivation process. At minimum, 
     *      partyUInfo shall include srcAddress. In our case, we end up setting the partyUInfo with
     *      sourceId instead and convert it to a 32 bit integer value as an array of bytes.
     * @param partyVInfo
     *      A bit string containing public information that is required by the application
     *      using this KDF to be contributed by party V to the key derivation process. At minimum, 
     *      partyVInfo shall include dstAddress. In our case, we end up setting the partyVInfo with 
     *      destId instead and convert it to a 32 bit integer value as an array of bytes.
     * @return
     *      Shared Secret key bytes array or also termed as DerivedKeyingMaterial generated after 
     *      Key Derivation function is a bit string of length keyDataLen
     */
NIST Concatenation Key Derivation function (KDF) per "Suite B Implementers' Guide to NIST SP 800-56A" section 5.
An approved Key Derivation function (KDF) shall be used to derive secret keying material from shared secret key.

@param hashAlg
Type of hash Algorithm used.
NIST Concatenation Key Derivation function ( KDF ) per " Suite B Implementers ' Guide to NIST SP 800 - 56A " section 5 . An approved Key Derivation function ( KDF ) shall be used to derive secret keying material from shared secret key . @param hashAlg Type of hash Algorithm used .
private static byte[] concatKDF(final String hashAlg, final byte[] sharedSecret, final int keyDataLen, 
          final byte[] algorithmID, final byte[] partyUInfo, final byte[] partyVInfo) 
    {
        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try 
        {
            baos.write(algorithmID);
            baos.write(partyUInfo);
            baos.write(partyVInfo);
        }
        catch (final IOException e)
        {
            throw new IllegalStateException(e);
        }
        final byte[] otherInfo = baos.toByteArray();
        final byte[] key = new byte[keyDataLen];
        final MessageDigest messageDigest;
        try 
        {
            messageDigest = MessageDigest.getInstance(hashAlg);
        } 
        catch (final NoSuchAlgorithmException e) 
        {
            throw new IllegalStateException("No such hashing algorithm");
        } 
        final int hashLen = messageDigest.getDigestLength(); 
        int reps = keyDataLen / hashLen;
        if (keyDataLen % hashLen != 0)
        {
            reps = reps + 1;
        }
        for (int i = 1; i <= reps; i++)
        {
            messageDigest.update(ByteBuffer.allocate(4).putInt(i).array());
            messageDigest.update(sharedSecret);
            messageDigest.update(otherInfo);
            final byte[] hash = messageDigest.digest();
            if (i < reps)
            {
                System.arraycopy(hash, 0, key, hashLen * (i - 1), hashLen);
            }
            else
            {
                if (keyDataLen % hashLen == 0)
                {
                    System.arraycopy(hash, 0, key, hashLen * (i - 1), hashLen);
                }
                else
                {
                    System.arraycopy(hash, 0, key, hashLen * (i - 1), keyDataLen % hashLen);
                }
            }
        }
        return key;
    }
private static byte [ ] concatKDF ( final String hashAlg , final byte [ ] sharedSecret , final int keyDataLen , final byte [ ] algorithmID , final byte [ ] partyUInfo , final byte [ ] partyVInfo ) { final ByteArrayOutputStream baos = new ByteArrayOutputStream ( ) ; try { baos . write ( algorithmID ) ; baos . write ( partyUInfo ) ; baos . write ( partyVInfo ) ; } catch ( final IOException e ) { throw new IllegalStateException ( e ) ; } final byte [ ] otherInfo = baos . toByteArray ( ) ; final byte [ ] key = new byte [ keyDataLen ] ; final MessageDigest messageDigest ; try { messageDigest = MessageDigest . getInstance ( hashAlg ) ; } catch ( final NoSuchAlgorithmException e ) { throw new IllegalStateException ( "No such hashing algorithm" ) ; } final int hashLen = messageDigest . getDigestLength ( ) ; int reps = keyDataLen / hashLen ; if ( keyDataLen % hashLen != 0 ) { reps = reps + 1 ; } for ( int i = 1 ; i <= reps ; i ++ ) { messageDigest . update ( ByteBuffer . allocate ( 4 ) . putInt ( i ) . array ( ) ) ; messageDigest . update ( sharedSecret ) ; messageDigest . update ( otherInfo ) ; final byte [ ] hash = messageDigest . digest ( ) ; if ( i < reps ) { System . arraycopy ( hash , 0 , key , hashLen * ( i - 1 ) , hashLen ) ; } else { if ( keyDataLen % hashLen == 0 ) { System . arraycopy ( hash , 0 , key , hashLen * ( i - 1 ) , hashLen ) ; } else { System . arraycopy ( hash , 0 , key , hashLen * ( i - 1 ) , keyDataLen % hashLen ) ; } } } return key ; }
NIST Concatenation Key Derivation function (KDF) per "Suite B Implementers' Guide to NIST SP 800-56A" section 5.
NIST Concatenation Key Derivation function ( KDF ) per " Suite B Implementers ' Guide to NIST SP 800 - 56A " section 5 .
//Each of the three fields: algorithmId, PartyUInfo and PartyVInfo shall be concatenated //in a fixed length sequence of substrings termed as otherInfo //new buffer capacity is 4 bytes NOCHECKSTYLE