org.bouncycastle.crypto.general.HMacDsaKCalculator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bc-fips Show documentation
Show all versions of bc-fips Show documentation
The FIPS 140-3 Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms certified to FIPS 140-3 level 1. This jar contains JCE provider and low-level API for the BC-FJA version 2.0.0, FIPS Certificate #4743. Please see certificate for certified platform details.
package org.bouncycastle.crypto.general;
import java.math.BigInteger;
import java.security.SecureRandom;
import org.bouncycastle.crypto.internal.Digest;
import org.bouncycastle.crypto.internal.macs.HMac;
import org.bouncycastle.crypto.internal.params.KeyParameterImpl;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.BigIntegers;
/**
* A deterministic K calculator based on the algorithm in section 3.2 of RFC 6979.
*/
class HMacDsaKCalculator
implements DsaKCalculator
{
private static final BigInteger ZERO = BigInteger.valueOf(0);
private final HMac hMac;
private final byte[] K;
private final byte[] V;
private BigInteger n;
/**
* Base constructor.
*
* @param digest digest to build the HMAC on.
*/
public HMacDsaKCalculator(Digest digest)
{
this.hMac = new HMac(digest);
this.V = new byte[hMac.getMacSize()];
this.K = new byte[hMac.getMacSize()];
}
public boolean isDeterministic()
{
return true;
}
public void init(BigInteger n, SecureRandom random)
{
throw new IllegalStateException("Operation not supported");
}
public void init(BigInteger n, BigInteger d, byte[] message)
{
this.n = n;
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 KeyParameterImpl(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 KeyParameterImpl(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 KeyParameterImpl(K));
hMac.update(V, 0, V.length);
hMac.doFinal(V, 0);
}
public BigInteger nextK()
{
byte[] t = new byte[((n.bitLength() + 7) / 8)];
for (;;)
{
int tOff = 0;
while (tOff < t.length)
{
hMac.update(V, 0, V.length);
hMac.doFinal(V, 0);
int len = Math.min(t.length - tOff, V.length);
System.arraycopy(V, 0, t, tOff, len);
tOff += len;
}
BigInteger k = bitsToInt(t);
if (k.compareTo(ZERO) > 0 && k.compareTo(n) < 0)
{
return k;
}
hMac.update(V, 0, V.length);
hMac.update((byte)0x00);
hMac.doFinal(K, 0);
hMac.init(new KeyParameterImpl(K));
hMac.update(V, 0, V.length);
hMac.doFinal(V, 0);
}
}
private BigInteger bitsToInt(byte[] t)
{
BigInteger v = new BigInteger(1, t);
if (t.length * 8 > n.bitLength())
{
v = v.shiftRight(t.length * 8 - n.bitLength());
}
return v;
}
}