public BitString MixKeys(BitString currentKey, BitString lastOutput, BitString secondToLastOutput) { switch (currentKey.BitLength) { case 128: return(currentKey.XOR(lastOutput.GetMostSignificantBits(128))); case 192: var mostSignificant16KeyBitStringXor = currentKey.GetMostSignificantBits(64).XOR( // XOR 64 most significant key bits w/ secondToLastOutput.Substring(0, 64) // the 64 least significant bits of the previous cipher text ); var leastSignificant128KeyBitStringXor = currentKey.GetLeastSignificantBits(128).XOR(lastOutput.GetMostSignificantBits(128)); return(mostSignificant16KeyBitStringXor.ConcatenateBits(leastSignificant128KeyBitStringXor)); case 256: var mostSignificantFirst16BitStringXor = currentKey.GetMostSignificantBits(128).XOR(secondToLastOutput.GetMostSignificantBits(128)); var leastSignificant16BitStringXor = currentKey.GetLeastSignificantBits(128).XOR(lastOutput.GetMostSignificantBits(128)); return(mostSignificantFirst16BitStringXor.ConcatenateBits(leastSignificant16BitStringXor)); default: throw new ArgumentException(nameof(currentKey)); } }
public byte[] HandleFinalFullPayloadBlockDecryption(BitString payload, IBlockCipherEngine engine, int numberOfBlocks, int originalPayloadBitLength) { // When payload is not a multiple of the block size if (numberOfBlocks > 1 && payload.BitLength % engine.BlockSizeBits != 0) { var numberOfBitsToAdd = engine.BlockSizeBits - payload.BitLength % engine.BlockSizeBits; // Decrypt the last full payload block (in this case the last block) var decryptedLastBlockBuffer = new byte[engine.BlockSizeBytes]; var lastBlock = payload.GetLeastSignificantBits(engine.BlockSizeBits).ToBytes(); engine.ProcessSingleBlock(lastBlock, decryptedLastBlockBuffer, 0); var paddedPayload = payload // The original payload minus the final full block .GetMostSignificantBits(payload.BitLength - engine.BlockSizeBits) // Add the least significant bits of the decrypted last block to pad to a multiple of the block size .ConcatenateBits(new BitString(decryptedLastBlockBuffer).GetLeastSignificantBits(numberOfBitsToAdd)) // Add the last block back onto the payload .ConcatenateBits(payload.GetLeastSignificantBits(engine.BlockSizeBits)); return(paddedPayload.ToBytes()); } return(payload.ToBytes()); }
/// <summary> /// Returns the EXACT number of bits needed to represent the <see cref="BigInteger"/> value. The MSbit is always a 1 /// </summary> /// <param name="value"></param> /// <returns></returns> public static BitString ExactBitString(this BigInteger value) { var bs = new BitString(value); var length = value.ExactBitLength(); return(bs.GetLeastSignificantBits(length)); }
private (BitString output, string error) Prf(BitString secret, string label, BitString seed, int outputLength) { int lengthToGenerate = outputLength.CeilingDivide(_shaHmac.OutputLength * _md5Hmac.OutputLength) * (_shaHmac.OutputLength * _md5Hmac.OutputLength); if (secret.BitLength % 8 != 0) { return(null, "Invalid secret, must be whole byte"); } var secretBytes = secret.BitLength / 8; var halfSecretLen = secretBytes.CeilingDivide(2) * 8; var firstHalf = secret.GetMostSignificantBits(halfSecretLen); var secondHalf = secret.GetLeastSignificantBits(halfSecretLen); var labelBytes = new BitString(Encoding.ASCII.GetBytes(label)); var md5Out = HmacPrf(_md5Hmac, firstHalf, labelBytes.ConcatenateBits(seed), lengthToGenerate); var shaOut = HmacPrf(_shaHmac, secondHalf, labelBytes.ConcatenateBits(seed), lengthToGenerate); if (md5Out.BitLength != shaOut.BitLength) { return(null, "Invalid PRF output, lenghts must be equal"); } var xorResult = md5Out.XOR(shaOut); return(xorResult.GetMostSignificantBits(outputLength), ""); }
private HashResult Md5Process(BitString message) { var lastIndex = _fullMessage.Length - 1; var spaceRemainingInLastBlock = SizeOfChunk - _fullMessage[lastIndex].BitLength; if (message.BitLength <= spaceRemainingInLastBlock) { // Message doesn't fill the block entirely, so add it and return success _fullMessage[lastIndex] = _fullMessage[lastIndex].ConcatenateBits(message); return(new HashResult(new BitString(0))); } else { // Fill out the last partial block _fullMessage[lastIndex] = _fullMessage[lastIndex].ConcatenateBits(message.GetMostSignificantBits(spaceRemainingInLastBlock)); // Add an empty block to the end (which is always needed for padding information anyways) _fullMessage = _fullMessage.Append(new BitString(0)).ToArray(); // Try to compress the last full block, if it fails, eject and fail var result = Md5Compress(_fullMessage[lastIndex]); if (!result.Success) { return(result); } // Figure out how many bits are left in the message and try to process them var trimmedMessage = message.GetLeastSignificantBits(message.BitLength - spaceRemainingInLastBlock); return(Md5Process(trimmedMessage)); } }
protected override BitString Wrap(BitString K, BitString S, bool wrapWithInverseCipher) { // 0. Pre-conditions var n = S.BitLength / 32; if ((n < 3) || (S.BitLength % 32 != 0)) { throw new ArgumentException($"Invalid {nameof(S)} length."); } var keylen = K.BitLength; var K2 = K.GetDeepCopy(); //if (keylen == 192) //{ // // Convert to 168 bits because TDES Block encrypt takes 168 bits // K2 = to168BitKey(K); // keylen = K2.BitLength; //} //else //{ // K2 = K; //} //if (keylen != 168) //{ // throw new ArgumentException($"Invalid {nameof(keylen)}"); //} // 1. Initialize variables // 1.a) Let s = 6(n-1) int s = 6 * (n - 1); // 1.b) Let S1,S2,...,Sn be the semi-blocks s.t. S=S1 || S2 || ... || Sn // 1.c) Let A0 = S1 BitString A = S.GetMostSignificantBits(32); // 1.d) For i=2,...,n: let Ri0 = Si BitString R2n = S.GetLeastSignificantBits(S.BitLength - 32); // 2. Calculate the intermediate values. For t = 1,...,s update variables // as follows: for (int t = 1; t <= s; ++t) { // a) A^t = MSB32(CIPH_K(A^t-1 || R2^t-1)) xor [t]32 BitString R2 = R2n.GetMostSignificantBits(32); //BitString t32 = to_bitstring32((unsigned long long)t); BitString t32 = BitString.To64BitString(t).GetLeastSignificantBits(32); var param = new ModeBlockCipherParameters(BlockCipherDirections.Encrypt, K2, A.ConcatenateBits(R2), wrapWithInverseCipher); BitString block_t = Cipher.ProcessPayload(param).Result; A = block_t.GetMostSignificantBits(32).XOR(t32); // b) For i=2,...,n: Ri^t = Ri+1^t-1 // c) Rn^t = LSB32(CIPH_K(CIPH_K(A^t-1 || R2^t-1))) R2n = R2n.GetLeastSignificantBits(R2n.BitLength - 32).ConcatenateBits(block_t.GetLeastSignificantBits(32)); } // 3. Output the results: // a) Let C1 = A^s // b) For i=2,...,n: Ci = Ri^s // c) Return C1 || C2 || ... || Cn return(A.ConcatenateBits(R2n)); }
public BitString GetNextIV() { var currentIV = _iv.GetLeastSignificantBits(_blockSize).GetDeepCopy(); _iv = _iv.BitStringAddition(BitString.One()); return(currentIV); }
protected override BitString WrapInverse(BitString K, BitString C, bool wrappedWithInverseCipher) { // 0. Pre-conditions int n = C.BitLength / 32; if ((n < 3) || (C.BitLength % 32 != 0)) { throw new ArgumentException($"Invalid {nameof(C)} length."); } int keyLength = K.BitLength; var K2 = K.GetDeepCopy(); //if (keyLength == 192) //{ // // Convert to 168 bits because TDES Block encrypt takes 168 bits // K2 = to168BitKey(K); // keyLength = K2.BitLength; //} //else //{ // K2 = K; //} //if (keyLength != 168) //{ // throw new ArgumentException($"Invalid {nameof(keyLength)}"); //} // 1. Initialize variables // 1.a) Let s = 6(n-1) int s = 6 * (n - 1); // 1.b) Let C1,C2,...,Cn be the semi-blocks s.t. C=C1 || C2 || ... || Cn // 1.c) Let As = C1 BitString A = C.GetMostSignificantBits(32); // 1.d) For i=2,...,n: let Ri0 = Ci BitString R2n = C.GetLeastSignificantBits(C.BitLength - 32); // 2. Calculate the intermediate values. For t = s, s-1, ..., 1, // update the variables as follows: for (int t = s; t >= 1; --t) { // a) A^t-1 = MSB(CIPH^-1K((A^t xor [t]32) || Rn^t)) BitString t32 = BitString.To64BitString(t).GetLeastSignificantBits(32); BitString Rn = R2n.GetLeastSignificantBits(32); var param = new ModeBlockCipherParameters(BlockCipherDirections.Decrypt, K2, A.XOR(t32).ConcatenateBits(Rn), wrappedWithInverseCipher); BitString block_t = Cipher.ProcessPayload(param).Result; A = block_t.GetMostSignificantBits(32); // b) R2^t-1 = LSB(CIPH^-1K((A^t xor [t]32) || Rn^t)) // c) For i=2,...,n-1, Ri+1^t-1 = Ri^t R2n = block_t.GetLeastSignificantBits(32).ConcatenateBits(R2n.GetMostSignificantBits(R2n.BitLength - 32)); } // 3. Output the results: // 3.a) Let S1 = A0 // 3.b) For i=2,...,n: Si = Ri0 // 3.c) Return S1 || S2 || ... || Sn return(A.ConcatenateBits(R2n)); }
protected override BitString Wrap(BitString K, BitString S, bool wrapWithInverseCipher) { // 0. Pre-conditions var n = S.BitLength / 64; if ((n < 3) || (S.BitLength % 64 != 0)) { throw new ArgumentException($"Invalid {nameof(S)} length."); } var keyLen = K.BitLength; if ((keyLen != 128) && (keyLen != 192) && (keyLen != 256)) { throw new ArgumentException($"Invalid {nameof(keyLen)}"); } // 1. Initialize variables // 1.a) Let s = 6(n-1) var s = 6 * (n - 1); // 1.b) Let S1,S2,...,Sn be the semi-blocks s.t. S=S1 || S2 || ... || Sn // 1.c) Let A0 = S1 var A = S.GetMostSignificantBits(64); // 1.d) For i=2,...,n: let Ri0 = Si var R2n = S.GetLeastSignificantBits(S.BitLength - 64); // 2. Calculate the intermediate values. For t = 1,...,s update variables // as follows: for (var t = 1; t <= s; ++t) { // a) A^t = MSB64(CIPH_K(A^t-1 || R2^t-1)) xor [t]64 var R2 = R2n.GetMostSignificantBits(64); var t64 = BitString.To64BitString(t); var block_t = Cipher.ProcessPayload( new ModeBlockCipherParameters( BlockCipherDirections.Encrypt, K, A.ConcatenateBits(R2), wrapWithInverseCipher )).Result; A = block_t.GetMostSignificantBits(64).XOR(t64); // b) For i=2,...,n: Ri^t = Ri+1^t-1 // c) Rn^t = LSB64(CIPH_K(CIPH_K(A^t-1 || R2^t-1))) R2n = R2n .GetLeastSignificantBits(R2n.BitLength - 64) .ConcatenateBits(block_t.GetLeastSignificantBits(64)); } // 3. Output the results: // a) Let C1 = A^s // b) For i=2,...,n: Ci = Ri^s // c) Return C1 || C2 || ... || Cn return(A.ConcatenateBits(R2n)); }
protected override BitString WrapInverse(BitString K, BitString C, bool wrappedWithInverseCipher) { // 0. Pre-conditions var n = C.BitLength / 64; if ((n < 3) || (C.BitLength % 64 != 0)) { throw new ArgumentException($"Invalid {nameof(C)} length."); } var aesKeyLength = K.BitLength; if ((aesKeyLength != 128) && (aesKeyLength != 192) && (aesKeyLength != 256)) { throw new ArgumentException($"Invalid {nameof(aesKeyLength)}"); } // 1. Initialize variables // 1.a) Let s = 6(n-1) var s = 6 * (n - 1); // 1.b) Let C1,C2,...,Cn be the semi-blocks s.t. C=C1 || C2 || ... || Cn // 1.c) Let As = C1 var A = C.GetMostSignificantBits(64); // 1.d) For i=2,...,n: let Ri0 = Ci var R2n = C.GetLeastSignificantBits(C.BitLength - 64); // 2. Calculate the intermediate values. For t = s, s-1, ..., 1, // update the variables as follows: for (var t = s; t >= 1; --t) { // a) A^t-1 = MSB(CIPH^-1K((A^t xor [t]64) || Rn^t)) var t64 = BitString.To64BitString(t); var Rn = R2n.GetLeastSignificantBits(64); var block_t = Cipher.ProcessPayload( new ModeBlockCipherParameters( BlockCipherDirections.Decrypt, K, A.XOR(t64).ConcatenateBits(Rn), wrappedWithInverseCipher )).Result; A = block_t.GetMostSignificantBits(64); // b) R2^t-1 = LSB(CIPH^-1K((A^t xor [t]64) || Rn^t)) // c) For i=2,...,n-1, Ri+1^t-1 = Ri^t R2n = block_t.GetLeastSignificantBits(64).ConcatenateBits(R2n.GetMostSignificantBits(R2n.BitLength - 64)); } // 3. Output the results: // 3.a) Let S1 = A0 // 3.b) For i=2,...,n: Si = Ri0 // 3.c) Return S1 || S2 || ... || Sn return(A.ConcatenateBits(R2n)); }
public override SymmetricCipherResult Decrypt(BitString key, BitString cipherText, bool wrappedWithInverseCipher) { // 1. Let ICV1 = 0xA6A6A6A6A6A6A6A6 // 2. Let S = W^-1(C) BitString s = WrapInverse(key, cipherText, wrappedWithInverseCipher); // 3. If MSB64(S) != ICV1 then return FAIL and stop. if (!s.GetMostSignificantBits(64).Equals(Icv1)) { return(new SymmetricCipherResult("Authentication failure.")); } // 4. Return P = LSB64(n-1)(S) BitString p = s.GetLeastSignificantBits((s.BitLength) - 64); return(new SymmetricCipherResult(p)); }
// NIST SP 800-38D // Recommendation for Block Cipher Modes of Operation: Galois/Counter // Mode (GCM) and GMAC // Section 6: Mathematical Components of GCM // Section 6.2: Incrementing Function // increment the rightmost s bits of X modulo 2^s // leave the leftmost len(X) - s bits unchanged public virtual BitString inc_s(int s, BitString X) { // inc_s(X) = MSB_len(X)-s || [int(LSB_s(X)) + 1 mod 2^s]_s if (X.BitLength < s) { return(null); } BigInteger lsp1 = X.GetLeastSignificantBits(s).ToPositiveBigInteger() + new BigInteger(1); //ThisLogger.Debug($"lsp1: {lsp1}"); lsp1 = lsp1 % (new BigInteger(1) << s); //ThisLogger.Debug($"lsp2: {lsp1}"); var bitsToAppend = new BitString(lsp1, s); //ThisLogger.Debug($"BitsToAppendLength: {bitsToAppend.Length}"); return(X.GetMostSignificantBits(X.BitLength - s).ConcatenateBits(bitsToAppend)); }
public BitString GetNextIV() { if (_iv.BitLength < _blockSize) { _iv = BitString.Zeroes(_blockSize - _iv.BitLength).ConcatenateBits(_iv); } var currentIV = _iv.GetLeastSignificantBits(_blockSize).GetDeepCopy(); // Avoid throwing an exception by subtracting from 000...0 if (currentIV.Equals(BitString.Zeroes(_blockSize))) { _iv = BitString.Ones(_blockSize); } else { _iv = _iv.BitStringSubtraction(BitString.One()); } return(currentIV); }
protected override DrbgResult GenerateAlgorithm(int requestedNumberOfBits, BitString additionalInput) { // 1 if (ReseedCounter > Attributes.MaxNumberOfRequestsBetweenReseeds) { return(new DrbgResult(DrbgStatus.ReseedRequired)); } // 2 if (additionalInput.BitLength != 0) { // 2.1 var dataToHash = new BitString("02") .ConcatenateBits(V) .ConcatenateBits(additionalInput); var w = _sha.HashMessage(dataToHash).Digest; // 2.2 V = V.BitStringAddition(w).GetLeastSignificantBits(HashAttributes.SeedLength); } // 3 var returnedBits = HashGen(V, requestedNumberOfBits); // 4 var H = _sha.HashMessage(new BitString("03").ConcatenateBits(V)).Digest; // 5 V = V.BitStringAddition(H); V = V.BitStringAddition(C); V = V.BitStringAddition(BitString.To32BitString(ReseedCounter)); V = V.GetLeastSignificantBits(HashAttributes.SeedLength); // 6 ReseedCounter++; // 7 return(new DrbgResult(returnedBits)); }
public void ShouldReturnCorrectOtherInfoCavsTests( KeyAgreementRole iutRole, OtherPartySharedInformation <FfcDomainParameters, FfcKeyPair> uPartySharedInformation, OtherPartySharedInformation <FfcDomainParameters, FfcKeyPair> vPartySharedInformation, int otherInfoLength, BitString expectedOtherInfo ) { string otherInfoPattern = "uPartyInfo||vPartyInfo"; TestableEntropyProvider entropyProvider = new TestableEntropyProvider(); // u/v party info comprised of ID, and dkmNonce, find the bitlength of both parties contributed information // to determine which bits are the "random" bits to inject into the TestableEntropyProvider. var composedBitLength = uPartySharedInformation.PartyId.BitLength + uPartySharedInformation.DkmNonce.BitLength + vPartySharedInformation.PartyId.BitLength; var entropyBits = expectedOtherInfo.GetLeastSignificantBits(expectedOtherInfo.BitLength - composedBitLength); entropyProvider.AddEntropy(entropyBits); var uPartyOtherInfo = new PartyOtherInfo(uPartySharedInformation.PartyId, uPartySharedInformation.DkmNonce); var vPartyOtherInfo = new PartyOtherInfo(vPartySharedInformation.PartyId, vPartySharedInformation.DkmNonce); _subject = new OtherInfo( entropyProvider, otherInfoPattern, otherInfoLength, KeyAgreementRole.InitiatorPartyU, uPartyOtherInfo, vPartyOtherInfo ); var result = _subject.GetOtherInfo(); Assert.AreEqual(expectedOtherInfo.ToHex(), result.ToHex()); }
public void TransformCiphertext(byte[] outBuffer, IBlockCipherEngine engine, int numberOfBlocks, int originalPayloadBitLength) { if (numberOfBlocks == 1 || originalPayloadBitLength % engine.BlockSizeBits == 0) { return; } var bitsToAddForPadding = numberOfBlocks * engine.BlockSizeBits - originalPayloadBitLength; var blockBitsWithoutPadding = engine.BlockSizeBits - bitsToAddForPadding; var newPayload = new BitString(outBuffer); var newPayloadUpToPadding = newPayload // all the blocks up to the second to last block, which should only include the "non padded" bits .GetMostSignificantBits(engine.BlockSizeBits * (numberOfBlocks - 2) + blockBitsWithoutPadding); var finalBlock = newPayload.GetLeastSignificantBits(engine.BlockSizeBits); var newPayloadBytes = newPayloadUpToPadding .ConcatenateBits(finalBlock) // Adding zero bits in the LSB to not add significant bits when converting to a byte array. .ConcatenateBits(BitString.Zeroes(bitsToAddForPadding)) .ToBytes(); Array.Copy(newPayloadBytes, 0, outBuffer, 0, newPayloadBytes.Length); }
private void Update(BitString seedMaterial) { BitString v = V.GetDeepCopy(); BitString key = Key.GetDeepCopy(); // 1. temp = Null BitString temp = new BitString(0); // 2. While (len(temp)<seedlen) do: while (temp.BitLength < CounterAttributes.SeedLength) { v = v .BitStringAddition(BitString.One()) .ConcatenateBits(new BitString(CounterAttributes.OutputLength - v.BitLength)); // Add zeroes to bitstring to make it the length of the OutputLength BitString outputBlock = BlockEncrypt(key, v); temp = temp.ConcatenateBits(outputBlock); } // 3. temp = Leftmost seedlen bits of temp temp = temp.GetMostSignificantBits(CounterAttributes.SeedLength); // 4. temp = temp xor provided_data Debug.Assert(temp.BitLength == seedMaterial.BitLength); temp = temp.XOR(seedMaterial); // 5. Key = Leftmost keylen bits of temp key = temp.GetMostSignificantBits(CounterAttributes.KeyLength); // 6. V = Rightmost outlen bits of temp v = temp.GetLeastSignificantBits(CounterAttributes.OutputLength); // 7. Return new values of Key and V Key = key.GetDeepCopy(); V = v.GetDeepCopy(); }
private BitString Divide(BitString a, BitString b) { if (b.Equals(BitString.Zeroes(b.BitLength))) { return(BitString.Zeroes(a.BitLength)); } var aBigInt = a.ToPositiveBigInteger(); var bBigInt = b.ToPositiveBigInteger(); var result = new BitString(aBigInt / bBigInt); // Ensure result is the same number of bits as a if (result.BitLength > a.BitLength) { result = result.GetLeastSignificantBits(a.BitLength); } else if (result.BitLength < a.BitLength) { result = BitString.Zeroes(a.BitLength - result.BitLength).ConcatenateBits(result); } return(result); }
/* * INPUT: The initial Msg is the length of the digest size * * MCT(Msg, MaxOutLen, MinOutLen, OutLenIncrement, MaxBlockSize, MinBlockSize) * { * Range = (MaxOutLen – MinOutLen + 1); * OutputLen = MaxOutLen; * BlockRange = (MaxBlockSize – MinBlockSize + 1); * BlockSize = MinBlockSize; * Customization = ""; * * Output[0] = Msg; * for (j = 0; j < 100; j++) * { * for (i = 1; i < 1001; i++) * { * InnerMsg = Left(Output[i-1] || ZeroBits(128), 128); * Output[i] = ParallelHash(InnerMsg, OutputLen, BlockSize, FunctionName, Customization); * Rightmost_Output_bits = Right(Output[i], 16); * OutputLen = MinOutLen + (floor((Rightmost_Output_bits % Range) / OutLenIncrement) * OutLenIncrement); * BlockSize = MinBlockSize + Right(Rightmost_Output_bits, 8) % BlockRange; * Customization = BitsToString(InnerMsg || Rightmost_Output_bits); * } * * OutputJ[j] = Output[1000]; * } * * return OutputJ; * } */ #endregion MonteCarloAlgorithm Pseudocode public MctResult <AlgoArrayResponseWithCustomization> MCTHash(HashFunction function, BitString message, MathDomain outputLength, MathDomain blockSizeDomain, bool hexCustomization, bool isSample) { _hexCustomization = hexCustomization; if (isSample) { NUM_OF_RESPONSES = 3; } var responses = new List <AlgoArrayResponseWithCustomization>(); var i = 0; var j = 0; var min = outputLength.GetDomainMinMax().Minimum; var max = outputLength.GetDomainMinMax().Maximum; var increment = outputLength.GetDomainMinMax().Increment; var minBlockSize = blockSizeDomain.GetDomainMinMax().Minimum; var maxBlockSize = blockSizeDomain.GetDomainMinMax().Maximum; var outputLen = max; var blockSize = minBlockSize; var blockSizeRange = (maxBlockSize - minBlockSize) + 1; var customization = ""; var range = (max - min) + 1; var innerMessage = message.GetDeepCopy(); try { for (i = 0; i < NUM_OF_RESPONSES; i++) { var innerDigest = new BitString(0); var iterationResponse = new AlgoArrayResponseWithCustomization() { }; iterationResponse.Message = innerMessage; iterationResponse.Customization = customization; iterationResponse.BlockSize = blockSize; for (j = 0; j < 1000; j++) { // Might not have 128 bits to pull from so we pad with 0 innerMessage = BitString.ConcatenateBits(innerMessage, BitString.Zeroes(128)) .GetMostSignificantBits(128); function.DigestLength = outputLen; var innerResult = _iParallelHash.HashMessage(function, innerMessage, blockSize, customization); innerDigest = innerResult.Digest.GetDeepCopy(); // Will always have 16 bits to pull from var rightmostBitString = innerDigest.GetLeastSignificantBits(16); var rightmostBits = rightmostBitString.Bits; outputLen = min + (int)System.Math.Floor((double)(rightmostBits.ToInt() % range) / increment) * increment; blockSize = minBlockSize + rightmostBitString.GetLeastSignificantBits(8).Bits.ToInt() % blockSizeRange; customization = GetStringFromBytes(BitString.ConcatenateBits(innerMessage, rightmostBitString).ToBytes()); innerMessage = innerDigest.GetDeepCopy(); } iterationResponse.Digest = innerDigest.GetDeepCopy(); responses.Add(iterationResponse); } } catch (Exception ex) { ThisLogger.Debug($"i count {i}, j count {j}"); ThisLogger.Error(ex); return(new MctResult <AlgoArrayResponseWithCustomization>($"{ex.Message}; {outputLen}")); } return(new MctResult <AlgoArrayResponseWithCustomization>(responses)); }
public void Update(byte[] input, int bitLength) { if (bitLength % 8 == 0 && _cachedBits.BitLength == 0) { BlockUpdate(input, 0, bitLength / 8); return; } var inputBits = new BitString(input).GetMostSignificantBits(bitLength); _cachedBits = BitString.ConcatenateBits(_cachedBits, inputBits); var numberOfCompletedBytes = _cachedBits.BitLength / 8; if (numberOfCompletedBytes > 0) { var completedBytes = _cachedBits.GetMostSignificantBits(numberOfCompletedBytes * 8); BlockUpdate(completedBytes.ToBytes(), 0, completedBytes.BitLength / 8); } _cachedBits = numberOfCompletedBytes * 8 == _cachedBits.BitLength ? new BitString(0) : _cachedBits.GetLeastSignificantBits(_cachedBits.BitLength - numberOfCompletedBytes * 8); }
public VerifyResult VerifyPadding(int nlen, BitString message, BigInteger embededMessage, PublicKey pubKey) { // 1. Signature Opening BigInteger irPrime; if (embededMessage % 16 == 12) { irPrime = embededMessage; } else if ((pubKey.N - embededMessage) % 16 == 12) { irPrime = pubKey.N - embededMessage; } else { return(new VerifyResult("Reject signature, failing modulo check")); } if (irPrime < NumberTheory.Pow2(nlen - 2) || irPrime > NumberTheory.Pow2(nlen - 1) - 1) { return(new VerifyResult("irPrime not within required range")); } // 2. Encapsulated Hash Verification var bsIrPrime = new BitString(irPrime, nlen); if (bsIrPrime.BitLength != nlen) { return(new VerifyResult("Bad bitlength for irPrime")); } if (!bsIrPrime.GetMostSignificantBits(4).Equals(Header)) { return(new VerifyResult("Header not found within first 4 bits")); } if (!bsIrPrime.GetLeastSignificantBits(8).Equals(Tail)) { return(new VerifyResult("Tail not found within last 8 bits")); } // check nibbles for Bs and A var expectedPaddingLen = nlen - Header.BitLength - Sha.HashFunction.OutputLen - GetTrailer().BitLength; var expectedPadding = GetPadding(expectedPaddingLen); var padding = bsIrPrime.MSBSubstring(4, expectedPaddingLen); if (!padding.Equals(expectedPadding)) { return(new VerifyResult("Improper padding, must be 'B's followed by 'A'")); } var beginOfHashIndex = expectedPaddingLen + 4; // 3. Hash Recovery var hashDigest = bsIrPrime.MSBSubstring(beginOfHashIndex, Sha.HashFunction.OutputLen); // 4. Message Hashing and Comparison var expectedHash = Sha.HashMessage(message).Digest; // check trailer for accuracy, including hash function var expectedTrailer = GetTrailer(); var trailer = bsIrPrime.GetLeastSignificantBits(expectedTrailer.BitLength); if (!expectedTrailer.Equals(trailer)) { return(new VerifyResult("Trailer hash functions do not match, bad signature")); } if (expectedHash.Equals(hashDigest)) { return(new VerifyResult()); } else { return(new VerifyResult("Hashes do not match, bad signature")); } }