public BigInteger Divide(BigInteger a, BigInteger b) { // Pulled from CAVS, EccMp.cpp, line 305 // EccMPPoly::DivMod var aLen = a.ExactBitLength(); var bLen = b.ExactBitLength(); // If a has less bits than the divisor, no division necessary if (aLen < bLen) { return(0); } b <<= ((aLen - bLen) + 1); var quotientBs = new BitString(aLen - bLen + 1); for (var i = aLen; i >= bLen; i--) { b >>= 1; if (a.GetBit(i - 1)) { // Set Quotient bit quotientBs.Set(i - bLen, true); a ^= b; } else { // Set Quotient bit quotientBs.Set(i - bLen, false); } } return(quotientBs.ToPositiveBigInteger()); }
public static void BitGetSetTest() { const int n = 250; var bitArray = new BitArray(n); var bitString = new BitString(n); for (var i = 0; i < n; i++) { var value = RandomHelpers.Default.NextBoolean(); bitArray.Set(i, value); bitString.Set(i, value); Assert.Equal(value, bitArray.Get(i)); Assert.Equal(value, bitString.Get(i)); } }
public BigInteger Multiply(BigInteger a, BigInteger b) { // Pulled from CAVS, EccMp.cpp, line 222 // EccMPPoly::operator* BigInteger shorter, longer; int shortLen, longLen; int aBitLen = a.ExactBitLength(); int bBitLen = b.ExactBitLength(); if (aBitLen < bBitLen) { shorter = a; shortLen = aBitLen; longer = b; longLen = bBitLen; } else { shorter = b; shortLen = bBitLen; longer = a; longLen = aBitLen; } var shorterBits = new BitString(shorter).Bits; var longerBits = new BitString(longer).Bits; var c = new BitString(shortLen + longLen); for (var i = 0; i < shortLen; i++) { if (!shorterBits[i]) { continue; } for (var j = 0; j < longLen; j++) { if (longerBits[j]) { c.Set(i + j, !c.Bits[i + j]); } } } return(Modulo(c.ToPositiveBigInteger())); }
private BitString to168BitKey(BitString K) { var Kc = new BitString(168); int ikc = 0; for (int ik = 0; ik < K.BitLength; ++ik) { if (ik % 8 != 0) { var b = K.Bits[ik]; Kc.Set(ikc++, b); } } return(Kc); }
public virtual BitString Getj0(BitString h, BitString iv) { BitString j0 = null; //ThisLogger.Debug("Getj0"); if (iv.BitLength == 96) { j0 = iv.ConcatenateBits(BitString.Zeroes(32)); j0.Set(0, true); } // If len(IV) != 96, then let s = 128 * ceil(len(IV)/128) - len(IV) // and let J0 = GHASH_H(IV || 0^(s + 64) || [len(IV)]_64) else { int s = 128 * iv.BitLength.CeilingDivide(128) - iv.BitLength; var x = iv .ConcatenateBits(BitString.Zeroes(s + 64)) .ConcatenateBits(BitString.To64BitString(iv.BitLength)); j0 = GHash(h, x); } return(j0); }
public MacResult Generate(BitString keyBits, BitString message, int macLength = 0) { // https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-38b.pdf //6.2 MAC Generation //Prerequisites: // block cipher CIPH with block size b; // key K; // MAC length parameter Tlen //Input: // message M of bit length Mlen. //Output: // MAC T of bit length Tlen. //Suggested Notation: // CMAC(K, M, Tlen) or, if Tlen is understood from the context, CMAC(K, M). //Steps: // 1. Apply the subkey generation process in Sec. 6.1 to K to produce K1 and K2. var subKeys = ComputeSubKey(keyBits); var K1 = subKeys.k1; var K2 = subKeys.k2; // 2. If Mlen = 0, let n = 1; else, let n = ceiling(Mlen / b). //var n = message.BitLength == 0 ? 1 : System.Math.Ceiling( // message.BitLength / (double)Engine.BlockSizeBits //); var n = message.BitLength == 0 ? 1 : message.BitLength.CeilingDivide(Engine.BlockSizeBits); // 3. Let M1, M2, ... , Mn - 1, Mn* denote the unique sequence of bit strings // such that M = M1 || M2 || ... || Mn - 1 || Mn*, // where M1, M2,..., Mn-1 are complete blocks.2 // 4. If Mn* is a complete block, let Mn = K1 XOR Mn*; //var numOfBlocks = (int)System.Math.Ceiling(message.BitLength / (double)_engine.BlockSizeBits); var numOfBlocks = message.BitLength.CeilingDivide(Engine.BlockSizeBits); var s1 = message.BitLength > Engine.BlockSizeBits ? message.MSBSubstring(0, (numOfBlocks - 1) * Engine.BlockSizeBits) : new BitString(0); var lastBlock = message.BitLength != 0 ? message.MSBSubstring(s1.BitLength, message.BitLength - s1.BitLength) : new BitString(0); if (message.BitLength % Engine.BlockSizeBits == 0 && message.BitLength != 0) { lastBlock = lastBlock.XOR(K1); } // else, let Mn = K2 XOR (Mn* || 10^j), where j = nb - Mlen - 1. else { var padding = new BitString(Engine.BlockSizeBits - lastBlock.BitLength); padding.Set(padding.BitLength - 1, true); lastBlock = K2.XOR(lastBlock.ConcatenateBits(padding)); } message = s1.ConcatenateBits(lastBlock).GetDeepCopy(); //if this was an empty message, it would have been padded with another block if (message.BitLength % Engine.BlockSizeBits != 0) { throw new Exception("Message isn't composed of same sized blocks."); } numOfBlocks = message.BitLength / Engine.BlockSizeBits; BitString prevC = new BitString(Engine.BlockSizeBits); BitString currC = new BitString(Engine.BlockSizeBits); for (var i = 0; i < numOfBlocks; i++) { var block = message.MSBSubstring(i * Engine.BlockSizeBits, Engine.BlockSizeBits); var param2 = new ModeBlockCipherParameters( BlockCipherDirections.Encrypt, keyBits, prevC.XOR(block) ); currC = AlgoMode.ProcessPayload(param2).Result; prevC = currC.GetDeepCopy(); } // 5. Let C0 = 0^b. // 6. For i = 1 to n, let Ci = CIPHK(Ci - 1 XOR Mi). // 7. Let T = MSBTlen(Cn). // 8. Return T. BitString mac; if (macLength != 0) { mac = currC.GetMostSignificantBits(macLength); } else { mac = currC.GetDeepCopy(); } return(new MacResult(mac)); }