private byte[] PSHA(byte[] secret,String label,byte[] data,int offset,int length) throws ServiceResultException {
  if (secret == null)   throw new IllegalArgumentException("ArgumentNullException: secret");
  if (offset < 0)   throw new IllegalArgumentException("ArgumentOutOfRangeException: offset");
  if (length < 0)   throw new IllegalArgumentException("ArgumentOutOfRangeException: offset");
  byte[] seed=label != null && !label.isEmpty() ? label.getBytes(UTF8) : null;
  if (data != null && data.length > 0) {
    if (seed != null) {
      ByteBuffer buf=ByteBuffer.allocate(seed.length + data.length);
      buf.put(seed);
      buf.put(data);
      buf.rewind();
      seed=buf.array();
    }
 else {
      seed=data;
    }
  }
  if (seed == null) {
    throw new ServiceResultException(StatusCodes.Bad_UnexpectedError,"The PSHA algorithm requires a non-null seed.");
  }
  SecurityPolicy policy=securityConfiguration.getSecurityPolicy();
  Mac hmac=CryptoUtil.createMac(policy.getKeyDerivationAlgorithm(),secret);
  hmac.update(seed);
  byte[] keySeed=hmac.doFinal();
  byte[] prfSeed=new byte[hmac.getMacLength() + seed.length];
  System.arraycopy(keySeed,0,prfSeed,0,keySeed.length);
  System.arraycopy(seed,0,prfSeed,keySeed.length,seed.length);
  byte[] output=new byte[length];
  int position=0;
  do {
    hmac.update(prfSeed);
    byte[] hash=hmac.doFinal();
    if (offset < hash.length) {
      for (int ii=offset; position < length && ii < hash.length; ii++) {
        output[position++]=hash[ii];
      }
    }
    if (offset > hash.length) {
      offset-=hash.length;
    }
 else {
      offset=0;
    }
    hmac.update(keySeed);
    keySeed=hmac.doFinal();
    System.arraycopy(keySeed,0,prfSeed,0,keySeed.length);
  }
 while (position < length);
  return output;
}

private byte [ ] PSHA ( byte [ ] secret , String label , byte [ ] data , int offset , int length ) throws ServiceResultException { if ( secret == null ) throw new IllegalArgumentException ( "ArgumentNullException: secret" ) ; if ( offset < 0 ) throw new IllegalArgumentException ( "ArgumentOutOfRangeException: offset" ) ; if ( length < 0 ) throw new IllegalArgumentException ( "ArgumentOutOfRangeException: offset" ) ; byte [ ] seed = label != null && ! label . isEmpty ( ) ? label . getBytes ( UTF8 ) : null ; if ( data != null && data . length > 0 ) { if ( seed != null ) { ByteBuffer buf = ByteBuffer . allocate ( seed . length + data . length ) ; buf . put ( seed ) ; buf . put ( data ) ; buf . rewind ( ) ; seed = buf . array ( ) ; } else { seed = data ; } } if ( seed == null ) { throw new ServiceResultException ( StatusCodes . Bad_UnexpectedError , "The PSHA algorithm requires a non-null seed." ) ; } SecurityPolicy policy = securityConfiguration . getSecurityPolicy ( ) ; Mac hmac = CryptoUtil . createMac ( policy . getKeyDerivationAlgorithm ( ) , secret ) ; hmac . update ( seed ) ; byte [ ] keySeed = hmac . doFinal ( ) ; byte [ ] prfSeed = new byte [ hmac . getMacLength ( ) + seed . length ] ; System . arraycopy ( keySeed , 0 , prfSeed , 0 , keySeed . length ) ; System . arraycopy ( seed , 0 , prfSeed , keySeed . length , seed . length ) ; byte [ ] output = new byte [ length ] ; int position = 0 ; do { hmac . update ( prfSeed ) ; byte [ ] hash = hmac . doFinal ( ) ; if ( offset < hash . length ) { for ( int ii = offset ; position < length && ii < hash . length ; ii ++ ) { output [ position ++ ] = hash [ ii ] ; } } if ( offset > hash . length ) { offset -= hash . length ; } else { offset = 0 ; } hmac . update ( keySeed ) ; keySeed = hmac . doFinal ( ) ; System . arraycopy ( keySeed , 0 , prfSeed , 0 , keySeed . length ) ; } while ( position < length ) ; return output ; }
generates a pseudo random sequence of bits using the p_sha1 or p_sha256 alhorithm . this function conforms with c # - implementation , so that keys returned from this function matches the c # - implementation keys .
