Example usage for org.bouncycastle.util Arrays fill

List of usage examples for org.bouncycastle.util Arrays fill

Introduction

In this page you can find the example usage for org.bouncycastle.util Arrays fill.

Prototype

public static void fill(short[] a, short val) 

Source Link

Usage

From source file:org.oscarehr.common.dao.RemoteDataLogDaoTest.java

License:Open Source License

@Test
public void testCreate() throws Exception {
    RemoteDataLog entity = new RemoteDataLog();
    EntityDataGenerator.generateTestDataForModelClass(entity);
    entity.setAction(Action.SEND);
    byte[] b = new byte[1024];
    Arrays.fill(b, (byte) 0x01);
    entity.setDocumentContents(b);//  w ww  . ja  v  a  2s.com
    dao.persist(entity);
    assertNotNull(entity.getId());
}

From source file:org.signserver.web.GenericProcessServletResponseTest.java

License:Open Source License

/**
 * Tests that the maximum upload size can be configured and is enforced.
 * @throws Exception /*from w w w  .  j a v a 2s .co  m*/
 */
@Test
public void test22MaxUploadSize() throws Exception {
    try {
        getGlobalSession().setProperty(GlobalConfiguration.SCOPE_GLOBAL, "HTTP_MAX_UPLOAD_SIZE", "700"); // 700 bytes max
        getGlobalSession().reload();

        Map<String, String> fields = new HashMap<String, String>();
        fields.put("workerName", getSignerNameCMSSigner1());

        // Test with a small number of bytes
        // Note we can not test with 700 bytes as there is also headers that take up space
        byte[] data = new byte[10];
        Arrays.fill(data, "a".getBytes("ASCII")[0]);
        fields.put("data", new String(data, "ASCII"));

        assertStatusReturned(fields, 200);

        // Test with more than 700 bytes upload
        data = new byte[701];
        Arrays.fill(data, "a".getBytes("ASCII")[0]);
        fields.put("data", new String(data, "ASCII"));

        assertStatusReturned(fields, 413);
    } finally {
        getGlobalSession().removeProperty(GlobalConfiguration.SCOPE_GLOBAL, "HTTP_MAX_UPLOAD_SIZE");
        getGlobalSession().reload();
    }
}

From source file:org.sufficientlysecure.keychain.securitytoken.SCP11bSecureMessaging.java

License:Open Source License

@Override
public CommandAPDU encryptAndSign(CommandAPDU apdu) throws SecureMessagingException {

    if (!isEstablished()) {
        throw new SecureMessagingException("not established");
    }//from  w w  w .j av  a 2  s  . c  o m

    ++mEncryptionCounter;
    if (mEncryptionCounter <= 0) {
        throw new SecureMessagingException("exhausted encryption counter");
    }

    try {

        byte[] data = apdu.getData();

        if (data.length > 0) {
            final Cipher cipher = Cipher.getInstance(SCP11_CIPHER_ALGO);

            byte[] iv = new byte[AES_BLOCK_SIZE];
            Arrays.fill(iv, (byte) 0);
            cipher.init(Cipher.ENCRYPT_MODE, mSEnc, new IvParameterSpec(iv));

            iv[AES_BLOCK_SIZE - 2] = (byte) ((mEncryptionCounter >> 8) & 0xff);
            iv[AES_BLOCK_SIZE - 1] = (byte) (mEncryptionCounter & 0xff);

            iv = cipher.doFinal(iv);

            cipher.init(Cipher.ENCRYPT_MODE, mSEnc, new IvParameterSpec(iv));

            final byte[] pdata = new byte[data.length + AES_BLOCK_SIZE - (data.length % AES_BLOCK_SIZE)];
            System.arraycopy(data, 0, pdata, 0, data.length);
            pdata[data.length] = (byte) 0x80;

            Arrays.fill(data, (byte) 0);

            data = cipher.doFinal(pdata);

            Arrays.fill(pdata, (byte) 0);
            Arrays.fill(iv, (byte) 0);
        }

        final int lcc = data.length + SCP11_MAC_LENGTH;

        final byte[] odata = new byte[4 + 3 + lcc + 3];
        int ooff = 0;

        odata[ooff++] = (byte) (((byte) apdu.getCLA()) | OPENPGP_SECURE_MESSAGING_CLA_MASK);
        odata[ooff++] = (byte) apdu.getINS();
        odata[ooff++] = (byte) apdu.getP1();
        odata[ooff++] = (byte) apdu.getP2();

        if (lcc > 0xff) {
            odata[ooff++] = (byte) 0;
            odata[ooff++] = (byte) ((lcc >> 8) & 0xff);
        }
        odata[ooff++] = (byte) (lcc & 0xff);

        System.arraycopy(data, 0, odata, ooff, data.length);
        ooff += data.length;

        Arrays.fill(data, (byte) 0);

        final Mac mac = Mac.getInstance(SCP11_MAC_ALGO, PROVIDER);
        mac.init(mSMac);
        mac.update(mMacChaining);
        mac.update(odata, 0, ooff);
        mMacChaining = mac.doFinal();

        System.arraycopy(mMacChaining, 0, odata, ooff, SCP11_MAC_LENGTH);
        ooff += SCP11_MAC_LENGTH;

        if (lcc > 0xff) {
            odata[ooff++] = (byte) 0;
        }
        odata[ooff++] = (byte) 0;

        apdu = new CommandAPDU(odata, 0, ooff);

        Arrays.fill(odata, (byte) 0);

        return apdu;

    } catch (NoSuchAlgorithmException e) {
        throw new SecureMessagingException("unavailable algorithm : " + e.getMessage());
    } catch (NoSuchProviderException e) {
        throw new SecureMessagingException("unavailable provider : " + e.getMessage());
    } catch (NoSuchPaddingException e) {
        throw new SecureMessagingException("unavailable padding algorithm : " + e.getMessage());
    } catch (InvalidKeyException e) {
        throw new SecureMessagingException("invalid key : " + e.getMessage());
    } catch (InvalidAlgorithmParameterException e) {
        throw new SecureMessagingException("invalid IV : " + e.getMessage());
    } catch (BadPaddingException e) {
        throw new SecureMessagingException("invalid IV : " + e.getMessage());
    } catch (IllegalBlockSizeException e) {
        throw new SecureMessagingException("invalid block size : " + e.getMessage());
    }
}

From source file:org.sufficientlysecure.keychain.securitytoken.SCP11bSecureMessaging.java

License:Open Source License

@Override
public ResponseAPDU verifyAndDecrypt(ResponseAPDU apdu) throws SecureMessagingException {

    if (!isEstablished()) {
        throw new SecureMessagingException("not established");
    }/*  w  w w  .j a v  a  2 s .  c om*/

    byte[] data = apdu.getData();

    if ((data.length == 0) && (apdu.getSW() != 0x9000) && (apdu.getSW1() != 0x62) && (apdu.getSW1() != 0x63)) {
        return apdu;
    }

    if (data.length < SCP11_MAC_LENGTH) {
        throw new SecureMessagingException("missing or incomplete MAC in response");
    }

    try {

        final Mac mac = Mac.getInstance(SCP11_MAC_ALGO, PROVIDER);
        mac.init(mSRMac);

        mac.update(mMacChaining);
        if ((data.length - SCP11_MAC_LENGTH) > 0) {
            mac.update(data, 0, data.length - SCP11_MAC_LENGTH);
        }
        mac.update((byte) apdu.getSW1());
        mac.update((byte) apdu.getSW2());

        final byte[] sig = mac.doFinal();

        for (int i = 0; i < SCP11_MAC_LENGTH; ++i) {
            if ((i >= sig.length) || (sig[i] != data[data.length - SCP11_MAC_LENGTH + i])) {
                throw new SecureMessagingException("corrupted integrity");
            }
        }

        if (((data.length - SCP11_MAC_LENGTH) % AES_BLOCK_SIZE) != 0) {
            throw new SecureMessagingException("invalid encrypted data size");
        }

        if (data.length > SCP11_MAC_LENGTH) {
            final Cipher cipher = Cipher.getInstance(SCP11_CIPHER_ALGO);

            byte[] iv = new byte[AES_BLOCK_SIZE];
            Arrays.fill(iv, (byte) 0);
            cipher.init(Cipher.ENCRYPT_MODE, mSEnc, new IvParameterSpec(iv));

            iv[0] = (byte) 0x80;
            iv[AES_BLOCK_SIZE - 2] = (byte) ((mEncryptionCounter >> 8) & 0xff);
            iv[AES_BLOCK_SIZE - 1] = (byte) (mEncryptionCounter & 0xff);

            iv = cipher.doFinal(iv);

            cipher.init(Cipher.DECRYPT_MODE, mSEnc, new IvParameterSpec(iv));
            data = cipher.doFinal(data, 0, data.length - SCP11_MAC_LENGTH);

            int i = data.length - 1;
            while ((0 < i) && (data[i] == (byte) 0))
                --i;

            if ((i <= 0) || (data[i] != (byte) 0x80)) {
                throw new SecureMessagingException("invalid data padding after decryption");
            }

            final byte[] datasw = new byte[i + 2];
            System.arraycopy(data, 0, datasw, 0, i);
            datasw[datasw.length - 2] = (byte) apdu.getSW1();
            datasw[datasw.length - 1] = (byte) apdu.getSW2();

            Arrays.fill(data, (byte) 0);

            data = datasw;
        } else {
            data = new byte[2];
            data[0] = (byte) apdu.getSW1();
            data[1] = (byte) apdu.getSW2();
        }

        apdu = new ResponseAPDU(data);

        return apdu;

    } catch (NoSuchAlgorithmException e) {
        throw new SecureMessagingException("unavailable algorithm : " + e.getMessage());
    } catch (NoSuchProviderException e) {
        throw new SecureMessagingException("unknown provider : " + e.getMessage());
    } catch (NoSuchPaddingException e) {
        throw new SecureMessagingException("unavailable padding algorithm : " + e.getMessage());
    } catch (InvalidKeyException e) {
        throw new SecureMessagingException("invalid key : " + e.getMessage());
    } catch (BadPaddingException e) {
        throw new SecureMessagingException("invalid IV : " + e.getMessage());
    } catch (InvalidAlgorithmParameterException e) {
        throw new SecureMessagingException("invalid IV : " + e.getMessage());
    } catch (IllegalBlockSizeException e) {
        throw new SecureMessagingException("invalid block size : " + e.getMessage());
    }
}

From source file:org.sufficientlysecure.keychain.securitytoken.SecurityTokenConnection.java

License:Open Source License

/**
 * Call DECIPHER command//  w w  w.ja  va2 s.  c om
 *
 * @param encryptedSessionKey the encoded session key
 * @param publicKey
 * @return the decoded session key
 */
public byte[] decryptSessionKey(@NonNull byte[] encryptedSessionKey, CanonicalizedPublicKey publicKey)
        throws IOException {
    final KeyFormat kf = mOpenPgpCapabilities.getFormatForKeyType(KeyType.ENCRYPT);

    if (!mPw1ValidatedForDecrypt) {
        verifyPinForOther();
    }

    byte[] data;
    byte[] dataLen;
    int pLen = 0;

    X9ECParameters x9Params;

    switch (kf.keyFormatType()) {
    case RSAKeyFormatType:
        data = Arrays.copyOfRange(encryptedSessionKey, 2, encryptedSessionKey.length);
        if (data[0] != 0) {
            data = Arrays.prepend(data, (byte) 0x00);
        }
        break;

    case ECKeyFormatType:
        pLen = ((((encryptedSessionKey[0] & 0xff) << 8) + (encryptedSessionKey[1] & 0xff)) + 7) / 8;
        data = new byte[pLen];

        System.arraycopy(encryptedSessionKey, 2, data, 0, pLen);

        final ECKeyFormat eckf = (ECKeyFormat) kf;
        x9Params = NISTNamedCurves.getByOID(eckf.getCurveOID());

        final ECPoint p = x9Params.getCurve().decodePoint(data);
        if (!p.isValid()) {
            throw new CardException("Invalid EC point!");
        }

        data = p.getEncoded(false);

        if (data.length < 128) {
            dataLen = new byte[] { (byte) data.length };
        } else {
            dataLen = new byte[] { (byte) 0x81, (byte) data.length };
        }
        data = Arrays.concatenate(Hex.decode("86"), dataLen, data);

        if (data.length < 128) {
            dataLen = new byte[] { (byte) data.length };
        } else {
            dataLen = new byte[] { (byte) 0x81, (byte) data.length };
        }
        data = Arrays.concatenate(Hex.decode("7F49"), dataLen, data);

        if (data.length < 128) {
            dataLen = new byte[] { (byte) data.length };
        } else {
            dataLen = new byte[] { (byte) 0x81, (byte) data.length };
        }
        data = Arrays.concatenate(Hex.decode("A6"), dataLen, data);
        break;

    default:
        throw new CardException("Unknown encryption key type!");
    }

    CommandApdu command = commandFactory.createDecipherCommand(data);
    ResponseApdu response = communicate(command);

    if (!response.isSuccess()) {
        throw new CardException("Deciphering with Security token failed on receive", response.getSw());
    }

    switch (mOpenPgpCapabilities.getFormatForKeyType(KeyType.ENCRYPT).keyFormatType()) {
    case RSAKeyFormatType:
        return response.getData();

    /* From 3.x OpenPGP card specification :
       In case of ECDH the card supports a partial decrypt only.
       With its own private key and the given public key the card calculates a shared secret
       in compliance with the Elliptic Curve Key Agreement Scheme from Diffie-Hellman.
       The shared secret is returned in the response, all other calculation for deciphering
       are done outside of the card.
            
       The shared secret obtained is a KEK (Key Encryption Key) that is used to wrap the
       session key.
            
       From rfc6637#section-13 :
       This document explicitly discourages the use of algorithms other than AES as a KEK algorithm.
       */
    case ECKeyFormatType:
        data = response.getData();

        final byte[] keyEnc = new byte[encryptedSessionKey[pLen + 2]];

        System.arraycopy(encryptedSessionKey, 2 + pLen + 1, keyEnc, 0, keyEnc.length);

        try {
            final MessageDigest kdf = MessageDigest
                    .getInstance(MessageDigestUtils.getDigestName(publicKey.getSecurityTokenHashAlgorithm()));

            kdf.update(new byte[] { (byte) 0, (byte) 0, (byte) 0, (byte) 1 });
            kdf.update(data);
            kdf.update(publicKey.createUserKeyingMaterial(fingerprintCalculator));

            final byte[] kek = kdf.digest();
            final Cipher c = Cipher.getInstance("AESWrap");

            c.init(Cipher.UNWRAP_MODE,
                    new SecretKeySpec(kek, 0, publicKey.getSecurityTokenSymmetricKeySize() / 8, "AES"));

            final Key paddedSessionKey = c.unwrap(keyEnc, "Session", Cipher.SECRET_KEY);

            Arrays.fill(kek, (byte) 0);

            return PGPPad.unpadSessionData(paddedSessionKey.getEncoded());
        } catch (NoSuchAlgorithmException e) {
            throw new CardException("Unknown digest/encryption algorithm!");
        } catch (NoSuchPaddingException e) {
            throw new CardException("Unknown padding algorithm!");
        } catch (PGPException e) {
            throw new CardException(e.getMessage());
        } catch (InvalidKeyException e) {
            throw new CardException("Invalid KEK!");
        }

    default:
        throw new CardException("Unknown encryption key type!");
    }
}

From source file:org.sufficientlysecure.keychain.securitytoken.SecurityTokenUtils.java

License:Open Source License

public static void writeBits(ByteArrayOutputStream stream, BigInteger value, int width) {
    if (value.signum() == -1) {
        throw new IllegalArgumentException("value is negative");
    } else if (width <= 0) {
        throw new IllegalArgumentException("width <= 0");
    }/*from   w  ww. j a  v a  2 s . co  m*/

    final byte[] prime = value.toByteArray();
    int skip = 0;

    while ((skip < prime.length) && (prime[skip] == 0))
        ++skip;

    if ((prime.length - skip) > width) {
        throw new IllegalArgumentException(
                "not enough width to fit value: " + (prime.length - skip) + "/" + width);
    }

    byte[] res = new byte[width];

    System.arraycopy(prime, skip, res, width - (prime.length - skip), prime.length - skip);

    stream.write(res, 0, width);
    Arrays.fill(res, (byte) 0);
    Arrays.fill(prime, (byte) 0);
}

From source file:org.sufficientlysecure.keychain.securitytoken.SecurityTokenUtilsTest.java

License:Open Source License

@Test
public void testPrivateKeyTemplateSimple2048() throws Exception {
    KeyFormat format = new KeyFormat(Hex.decode("010000001800"));
    RSAPrivateCrtKey key2048 = mock(RSAPrivateCrtKey.class);
    byte[] tmp = new byte[128];
    Arrays.fill(tmp, (byte) 0x11);
    when(key2048.getPrimeP()).thenReturn(new BigInteger(tmp));

    Arrays.fill(tmp, (byte) 0x12);
    when(key2048.getPrimeQ()).thenReturn(new BigInteger(tmp));

    when(key2048.getPublicExponent()).thenReturn(new BigInteger("65537"));

    Assert.assertArrayEquals(Hex.decode("4d820115" + // Header TL
            "a400" + // CRT
            "7f4808" + // 8 bytes
            "9103" + // e
            "928180" + // p
            "938180" + // q
            "5f48820103" +

            "010001" +

            "1111111111111111111111111111111111111111111111111111111111111111"
            + "1111111111111111111111111111111111111111111111111111111111111111"
            + "1111111111111111111111111111111111111111111111111111111111111111"
            + "1111111111111111111111111111111111111111111111111111111111111111" +

            "1212121212121212121212121212121212121212121212121212121212121212"
            + "1212121212121212121212121212121212121212121212121212121212121212"
            + "1212121212121212121212121212121212121212121212121212121212121212"
            + "1212121212121212121212121212121212121212121212121212121212121212"),
            SecurityTokenUtils.createPrivKeyTemplate(key2048, KeyType.AUTH, format));
}

From source file:org.sufficientlysecure.keychain.ui.base.BaseSecurityTokenNfcActivity.java

License:Open Source License

/**
 * Puts a key on the token in the given slot.
 *
 * @param slot The slot on the token where the key should be stored:
 *             0xB6: Signature Key//from  w w w .ja va2  s  . com
 *             0xB8: Decipherment Key
 *             0xA4: Authentication Key
 */
public void nfcPutKey(int slot, CanonicalizedSecretKey secretKey, Passphrase passphrase) throws IOException {
    if (slot != 0xB6 && slot != 0xB8 && slot != 0xA4) {
        throw new IOException("Invalid key slot");
    }

    RSAPrivateCrtKey crtSecretKey;
    try {
        secretKey.unlock(passphrase);
        crtSecretKey = secretKey.getCrtSecretKey();
    } catch (PgpGeneralException e) {
        throw new IOException(e.getMessage());
    }

    // Shouldn't happen; the UI should block the user from getting an incompatible key this far.
    if (crtSecretKey.getModulus().bitLength() > 2048) {
        throw new IOException("Key too large to export to Security Token.");
    }

    // Should happen only rarely; all GnuPG keys since 2006 use public exponent 65537.
    if (!crtSecretKey.getPublicExponent().equals(new BigInteger("65537"))) {
        throw new IOException("Invalid public exponent for smart Security Token.");
    }

    if (!mPw3Validated) {
        nfcVerifyPin(0x83); // (Verify PW3 with mode 83)
    }

    byte[] header = Hex.decode("4D82" + "03A2" // Extended header list 4D82, length of 930 bytes. (page 23)
            + String.format("%02x", slot) + "00" // CRT to indicate targeted key, no length
            + "7F48" + "15" // Private key template 0x7F48, length 21 (decimal, 0x15 hex)
            + "9103" // Public modulus, length 3
            + "928180" // Prime P, length 128
            + "938180" // Prime Q, length 128
            + "948180" // Coefficient (1/q mod p), length 128
            + "958180" // Prime exponent P (d mod (p - 1)), length 128
            + "968180" // Prime exponent Q (d mod (1 - 1)), length 128
            + "97820100" // Modulus, length 256, last item in private key template
            + "5F48" + "820383");// DO 5F48; 899 bytes of concatenated key data will follow
    byte[] dataToSend = new byte[934];
    byte[] currentKeyObject;
    int offset = 0;

    System.arraycopy(header, 0, dataToSend, offset, header.length);
    offset += header.length;
    currentKeyObject = crtSecretKey.getPublicExponent().toByteArray();
    System.arraycopy(currentKeyObject, 0, dataToSend, offset, 3);
    offset += 3;
    // NOTE: For a 2048-bit key, these lengths are fixed. However, bigint includes a leading 0
    // in the array to represent sign, so we take care to set the offset to 1 if necessary.
    currentKeyObject = crtSecretKey.getPrimeP().toByteArray();
    System.arraycopy(currentKeyObject, currentKeyObject.length - 128, dataToSend, offset, 128);
    Arrays.fill(currentKeyObject, (byte) 0);
    offset += 128;
    currentKeyObject = crtSecretKey.getPrimeQ().toByteArray();
    System.arraycopy(currentKeyObject, currentKeyObject.length - 128, dataToSend, offset, 128);
    Arrays.fill(currentKeyObject, (byte) 0);
    offset += 128;
    currentKeyObject = crtSecretKey.getCrtCoefficient().toByteArray();
    System.arraycopy(currentKeyObject, currentKeyObject.length - 128, dataToSend, offset, 128);
    Arrays.fill(currentKeyObject, (byte) 0);
    offset += 128;
    currentKeyObject = crtSecretKey.getPrimeExponentP().toByteArray();
    System.arraycopy(currentKeyObject, currentKeyObject.length - 128, dataToSend, offset, 128);
    Arrays.fill(currentKeyObject, (byte) 0);
    offset += 128;
    currentKeyObject = crtSecretKey.getPrimeExponentQ().toByteArray();
    System.arraycopy(currentKeyObject, currentKeyObject.length - 128, dataToSend, offset, 128);
    Arrays.fill(currentKeyObject, (byte) 0);
    offset += 128;
    currentKeyObject = crtSecretKey.getModulus().toByteArray();
    System.arraycopy(currentKeyObject, currentKeyObject.length - 256, dataToSend, offset, 256);

    String putKeyCommand = "10DB3FFF";
    String lastPutKeyCommand = "00DB3FFF";

    // Now we're ready to communicate with the token.
    offset = 0;
    String response;
    while (offset < dataToSend.length) {
        int dataRemaining = dataToSend.length - offset;
        if (dataRemaining > 254) {
            response = nfcCommunicate(putKeyCommand + "FE" + Hex.toHexString(dataToSend, offset, 254));
            offset += 254;
        } else {
            int length = dataToSend.length - offset;
            response = nfcCommunicate(lastPutKeyCommand + String.format("%02x", length)
                    + Hex.toHexString(dataToSend, offset, length));
            offset += length;
        }

        if (!response.endsWith("9000")) {
            throw new CardException("Key export to Security Token failed", parseCardStatus(response));
        }
    }

    // Clear array with secret data before we return.
    Arrays.fill(dataToSend, (byte) 0);
}

From source file:org.sufficientlysecure.keychain.util.SecurityTokenUtils.java

License:Open Source License

public static void writeBits(ByteArrayOutputStream stream, BigInteger value, int width) {
    if (value.signum() == -1) {
        throw new IllegalArgumentException("value is negative");
    } else if (width <= 0) {
        throw new IllegalArgumentException("width <= 0");
    }//from   w  w  w  .j a v a2s. c  om

    byte[] prime = value.toByteArray();
    int stripIdx = 0;
    while (prime[stripIdx] == 0 && stripIdx + 1 < prime.length) {
        stripIdx++;
    }

    if (prime.length - stripIdx > width) {
        throw new IllegalArgumentException("not enough width to fit value: " + prime.length + "/" + width);
    }
    byte[] res = new byte[width];
    int empty = width - (prime.length - stripIdx);

    System.arraycopy(prime, stripIdx, res, Math.max(0, empty), Math.min(prime.length, width));

    stream.write(res, 0, width);
    Arrays.fill(res, (byte) 0);
    Arrays.fill(prime, (byte) 0);
}

From source file:us.eharning.atomun.core.ec.internal.RFC6979KCalculator.java

License:Open Source License

public void init(BigInteger n, BigInteger d, byte[] message) {
    this.n = n;// w w w  . ja  v a2 s.  c om

    Arrays.fill(V, (byte) 0x01);
    Arrays.fill(K, (byte) 0);

    byte[] x = new byte[(n.bitLength() + 7) / 8];
    byte[] dVal = BigIntegers.asUnsignedByteArray(d);

    System.arraycopy(dVal, 0, x, x.length - dVal.length, dVal.length);

    byte[] m = new byte[(n.bitLength() + 7) / 8];

    BigInteger mInt = bitsToInt(message);

    if (mInt.compareTo(n) >= 0) {
        mInt = mInt.subtract(n);
    }

    byte[] mVal = BigIntegers.asUnsignedByteArray(mInt);

    System.arraycopy(mVal, 0, m, m.length - mVal.length, mVal.length);

    hMac.init(new KeyParameter(K));

    hMac.update(V, 0, V.length);
    hMac.update((byte) 0x00);
    hMac.update(x, 0, x.length);
    hMac.update(m, 0, m.length);

    hMac.doFinal(K, 0);

    hMac.init(new KeyParameter(K));

    hMac.update(V, 0, V.length);

    hMac.doFinal(V, 0);

    hMac.update(V, 0, V.length);
    hMac.update((byte) 0x01);
    hMac.update(x, 0, x.length);
    hMac.update(m, 0, m.length);

    hMac.doFinal(K, 0);

    hMac.init(new KeyParameter(K));

    hMac.update(V, 0, V.length);

    hMac.doFinal(V, 0);
}