public void ShouldCorrectlyConvert168BitKeyTo192BitKey(string keyHex, string expectedHex) { var k = new BitString(keyHex); var expected = new BitString(expectedHex); var result = _subject.Convert168BitKeyTo192BitKey_public(k); var expectedArr = new BitString[3]; expectedArr[0] = expected.MSBSubstring(0, 64); expectedArr[1] = expected.MSBSubstring(64, 64); expectedArr[2] = expected.MSBSubstring(64 * 2, 64); var resultArr = new BitString[3]; resultArr[0] = result.MSBSubstring(0, 64); resultArr[1] = result.MSBSubstring(64, 64); resultArr[2] = result.MSBSubstring(64 * 2, 64); for (var i = 0; i < 3; i++) { Assert.AreEqual(expectedArr[i], resultArr[i], $"{i}"); } Assert.AreEqual(expected, result, "whole"); }
public override SymmetricCipherResult Decrypt(BitString key, BitString cipherText, bool wrappedWithInverseCipher) { // 0. Check for valid bitlength ciphertext if (cipherText.BitLength < 128 || cipherText.BitLength % 64 != 0) { return(new SymmetricCipherResult("Invalid length for ciphertext")); } // 1. Let n = number of semi-blocks in C (number of half-blocks, where a block is 128-bits) var n = cipherText.BitLength / 64; // 2. Let ICV2 = 0xA65959A6 // 3. Set S based on semi-blocks var S = new BitString(32); if (n == 2) { var aesResult = Cipher.ProcessPayload(new ModeBlockCipherParameters(BlockCipherDirections.Decrypt, key, cipherText, wrappedWithInverseCipher)); if (!aesResult.Success) { return(new SymmetricCipherResult(aesResult.ErrorMessage)); } S = aesResult.Result; } else if (n > 2) { S = WrapInverse(key, cipherText, wrappedWithInverseCipher); } // 4. Check MSB(S, 32) to be equal to ICV2 if (!S.MSBSubstring(0, 32).Equals(Icv2)) { return(new SymmetricCipherResult("ICV2 not found as most significant bits of S")); } // 5. pLen = int(LSB(MSB(S, 64), 32)) var pLen = (int)S.MSBSubstring(0, 64).Substring(0, 32).ToPositiveBigInteger(); // 6. padLen = 8 * (n - 1) - pLen var padLen = 8 * (n - 1) - pLen; // 7. Make sure 0 < padLen < 7 if (padLen < 0 || padLen > 7) { return(new SymmetricCipherResult("Invalid padLen")); } // 8. If the padding isn't 0s, then fail if (!S.Substring(0, 8 * padLen).Equals(BitString.Zeroes(8 * padLen))) { return(new SymmetricCipherResult("Padding is not all 0s")); } // 9. Return p = MSB(LSB(S, 64*(n-1)), 8*pLen) var p = S.Substring(0, 64 * (n - 1)).MSBSubstring(0, 8 * pLen); return(new SymmetricCipherResult(p)); }
// Computes Kc as described in rfc 8554 public BitString Algorithm4b(BitString sig, BitString msg, BitString pubType, BitString I, BitString q) { // 1. If the signature is not at least four bytes long, return INVALID. if (sig.BitLength < 32) { return(null); } // 2. Parse sigtype, C, and y from the signature as follows: // a. sigtype = strTou32(first 4 bytes of signature) var sigType = sig.MSBSubstring(0, 32); // b. If sigtype is not equal to pubtype, return INVALID. if (!pubType.Equals(sigType)) { return(null); } // c. Set n and p according to the pubtype and Table 1; if the signature is not exactly 4 + n * (p + 1) // bytes long, return INVALID. var p = LmotsModeMapping.GetPFromCode(sigType); var n = LmotsModeMapping.GetNFromCode(sigType); if (sig.BitLength != (4 + (n * (p + 1))) * 8) { return(null); } // d. C = next n bytes of signature var C = sig.MSBSubstring(32, n * 8); // e. y[0] = next n bytes of signature // y[1] = next n bytes of signature // ... // y[p - 1] = next n bytes of signature var y = sig.MSBSubstring((n * 8) + 32, p * n * 8); // 3. Compute the string Kc as described in rfc 8554 var Q = _sha256.HashMessage(I .ConcatenateBits(q) .ConcatenateBits(D_MESG) .ConcatenateBits(C) .ConcatenateBits(msg)).Digest; var cksmQ = CheckSum(Q); var QcksmQ = Q.ConcatenateBits(cksmQ); var z = LmsDllLoader.GenZ(_p, _n, _w, y.ToBytes(), QcksmQ.ToBytes(), I.ToBytes(), q.ToBytes()); var concatenated = I.ConcatenateBits(q).ConcatenateBits(D_PBLC); concatenated = concatenated.ConcatenateBits(new BitString(z)); var Kc = _sha256.HashMessage(concatenated).Digest; // 4. Return Kc. return(Kc); }
public static BitString SubString(BitString X, int start, int end) { if (start >= end || start >= X.BitLength) { return(new BitString(0)); } else if (end <= X.BitLength) { return(X.MSBSubstring(start, end - start)); } else { return(X.MSBSubstring(start, X.BitLength - start)); } }
public LmotsVerificationResult VerifyLmotsSignature(BitString sig, BitString publicKey, BitString msg) { // 1. If the public key is not at least four bytes long, return INVALID. if (publicKey.BitLength < 32) { return(new LmotsVerificationResult("Validation failed. Public key wrong length.")); } // 2. Parse pubtype, I, q, and K from the public key as follows: // a. pubtype = strTou32(first 4 bytes of public key) var pubType = publicKey.MSBSubstring(0, 32); // b. Set n according to the pubkey and Table 1; if the public key is not exactly 24 + n bytes long, return INVALID. var n = LmotsModeMapping.GetNFromCode(pubType); if (publicKey.BitLength != (n + 24) * 8) { return(new LmotsVerificationResult("Validation failed. Public key wrong length.")); } // c. I = next 16 bytes of public key var I = publicKey.MSBSubstring(32, 128); // d. q = strTou32(next 4 bytes of public key) var q = publicKey.MSBSubstring(160, 32); // e. K = next n bytes of public key var K = publicKey.MSBSubstring(192, n * 8); // 3. Compute the public key candidate Kc from the signature, message, pubtype, and the identifiers I and q // obtained from the public key, using Algorithm 4b.If Algorithm 4b returns INVALID, then return INVALID. var Kc = Algorithm4b(sig, msg, pubType, I, q); if (Kc == null) { return(new LmotsVerificationResult("Validation failed. Computing Kc failed.")); } // 4. If Kc is equal to K, return VALID; otherwise, return INVALID. if (K.Equals(Kc)) { return(new LmotsVerificationResult()); } else { return(new LmotsVerificationResult("Validation failed. Signature does not match.")); } }
// Public for use in HashConditioningComponent public DrbgResult Hash_Df(BitString data, int bitsToReturn) { // 0 if (bitsToReturn > 255 * HashAttributes.OutputLength) { throw new ArgumentException("Requesting too many bits to return"); } // 1 var temp = new BitString(0); // 2 var len = bitsToReturn.CeilingDivide(HashAttributes.OutputLength); // 3 var counter = new BitString("01"); // 4 for (var i = 0; i < len; i++) { // 4.1 var dataToHash = counter.ConcatenateBits(BitString.To32BitString(bitsToReturn)).ConcatenateBits(data); temp = temp.ConcatenateBits(_sha.HashMessage(dataToHash).Digest); // 4.2 counter = counter.BitStringAddition(BitString.One()); } // 5 var requestedBits = temp.MSBSubstring(0, bitsToReturn); // 6 return(new DrbgResult(requestedBits)); }
public FfcVerificationResult Verify(FfcDomainParameters domainParameters, FfcKeyPair keyPair, BitString message, FfcSignature signature, bool skipHash = false) { // 1 if (signature.R < 0 || signature.R > domainParameters.Q) { return(new FfcVerificationResult("Invalid r provided")); } if (signature.S < 0 || signature.S > domainParameters.Q) { return(new FfcVerificationResult("Invalid s provided")); } // 2 var w = signature.S.ModularInverse(domainParameters.Q); var zLen = System.Math.Min(Sha.HashFunction.OutputLen, new BitString(domainParameters.Q).BitLength); var z = BitString.MSBSubstring(Sha.HashMessage(message).Digest, 0, zLen).ToPositiveBigInteger(); var u1 = (z * w) % domainParameters.Q; var u2 = (signature.R * w) % domainParameters.Q; // (g^u1 * y^u2) mod p == [(g^u1 mod p) * (y^u2 mod p)] mod p var v = ((BigInteger.ModPow(domainParameters.G, u1, domainParameters.P) * BigInteger.ModPow(keyPair.PublicKeyY, u2, domainParameters.P)) % domainParameters.P) % domainParameters.Q; // 3 if (v != signature.R) { return(new FfcVerificationResult("Invalid v, does not match provided r")); } return(new FfcVerificationResult()); }
private BitString HashGen(BitString v, int bitsToReturn) { // 1 var m = bitsToReturn / HashAttributes.OutputLength + (bitsToReturn % HashAttributes.OutputLength != 0 ? 1 : 0); // 2 var data = v.GetDeepCopy(); // 3 var W = new BitString(0); // 4 for (var i = 0; i < m; i++) { // 4.1 var w = _sha.HashMessage(data).Digest; // 4.2 W = W.ConcatenateBits(w); // 4.3 data = data.BitStringAddition(BitString.One()).GetLeastSignificantBits(HashAttributes.SeedLength); } // 5 var returnedBits = W.MSBSubstring(0, bitsToReturn); // 6 return(returnedBits); }
// As described on page 8 of RFC 8554 private BigInteger Coef(BitString S, int i, int w) { var resultlhs = new BitString(new BigInteger((1 << w) - 1)); var resultrhs = new BitString(S.MSBSubstring(i * w / 8 * 8, 8).ToPositiveBigInteger() >> (8 - (w * (i % (8 / w)) + w))); return(resultlhs.AND(resultrhs).ToPositiveBigInteger()); }
public KdfResult DeriveKey(BitString kI, BitString fixedData, int len, BitString iv = null, int breakLocation = 0) { // 1 var n = len.CeilingDivide(Mac.OutputLength); // 2 if (n > NumberTheory.Pow2(_counterLength) - 1) { return(new KdfResult("Counter length too long for operation")); } // 3 var result = new BitString(0); // 4 if (_counterLocation == CounterLocations.MiddleFixedData) { if (breakLocation < 1 || breakLocation > fixedData.BitLength - 1) { return(new KdfResult("Invalid break location")); } } for (var i = 1; i <= n; i++) { var counterBits = BitString.To32BitString(i).GetLeastSignificantBits(_counterLength); var data = new BitString(0); switch (_counterLocation) { case CounterLocations.BeforeFixedData: data = data.ConcatenateBits(counterBits).ConcatenateBits(fixedData); break; case CounterLocations.AfterFixedData: data = data.ConcatenateBits(fixedData).ConcatenateBits(counterBits); break; case CounterLocations.MiddleFixedData: var firstPart = fixedData.GetMostSignificantBits(breakLocation); var secondPart = fixedData.MSBSubstring(breakLocation, fixedData.BitLength - breakLocation); data = data.ConcatenateBits(firstPart).ConcatenateBits(counterBits).ConcatenateBits(secondPart); break; default: return(new KdfResult("Invalid Counter location")); } var kTemp = PseudoRandomFunction(kI, data); result = result.ConcatenateBits(kTemp); } // 5 var kOut = result.GetMostSignificantBits(len); return(new KdfResult(kOut)); }
/* * INPUT: The initial Msg of 256 bits long * LmsParams * SEED * RootI * * { * lmsKeyPair = GenerateLmsKeyPair(SEED, RootI, Params); * Output0 = Msg; * for (j=0; j<100; j++) { * for (i=1; i<(isSample ? 101 : 1001); i++) { * M[i] = leftmost bits indexed from 96 to 352; * if (lmsKeyPair is expired) { * lmsKeyPair = GenerateLmsKeyPair(M[i], 128 left most bits of M[i], Params); * } * Output[i] = LmsSignature(M[i],lmsKeyPair); * lmsKeyPair = UpdateLmsKeyPair(lmsKeyPair); * } * Output[j] = Output[1000]; * OUTPUT: Output[j] * } * } */ #endregion MonteCarloAlgorithm Pseudocode public async Task <MCTResult <AlgoArrayResponse> > MCTHashAsync(LmsType[] lmsTypes, LmotsType[] lmotsTypes, BitString seed, BitString rootI, BitString message, bool isSample) { var hss = _hssFactory.GetInstance(lmsTypes.Length, lmsTypes, lmotsTypes, EntropyProviderTypes.Testable, seed, rootI); var keyPair = await hss.GenerateHssKeyPairAsync(); if (isSample) { NUM_OF_RESPONSES = 3; } var responses = new List <AlgoArrayResponse>(); var i = 0; var j = 0; var innerMessage = message.GetDeepCopy(); try { for (i = 0; i < NUM_OF_RESPONSES; i++) { var innerSignature = new BitString(0); var iterationResponse = new AlgoArrayResponse() { }; iterationResponse.Message = innerMessage; for (j = 0; j < (isSample ? 100 : 1000); j++) { if (keyPair.Expired) { hss = _hssFactory.GetInstance(lmsTypes.Length, lmsTypes, lmotsTypes, EntropyProviderTypes.Testable, innerMessage, innerMessage.MSBSubstring(0, 128)); keyPair = await hss.GenerateHssKeyPairAsync(); } innerSignature = (await hss.GenerateHssSignatureAsync(innerMessage, keyPair)).Signature; keyPair = await hss.UpdateKeyPairOneStepAsync(keyPair); innerMessage = innerSignature.MSBSubstring(96, 256); } iterationResponse.Signature = innerSignature.GetDeepCopy(); responses.Add(iterationResponse); } } catch (Exception ex) { ThisLogger.Debug($"i count {i}, j count {j}"); ThisLogger.Error(ex); return(new MCTResult <AlgoArrayResponse>($"{ex.Message}")); } return(new MCTResult <AlgoArrayResponse>(responses)); }
public BitString Mask(BitString seed, int maskLen) { var T = new BitString(0); var iterations = maskLen.CeilingDivide(_sha.HashFunction.OutputLen) - 1; for (var i = 0; i <= iterations; i++) { var dig = _sha.HashMessage(BitString.ConcatenateBits(seed, BitString.To32BitString(i))).Digest; T = BitString.ConcatenateBits(T, dig); } return(T.MSBSubstring(0, maskLen)); }
private Common.Symmetric.MCTResult <AlgoArrayResponse> Encrypt(IModeBlockCipherParameters param) { var responses = new List <AlgoArrayResponse> { new AlgoArrayResponse { IV = param.Iv, Keys = param.Key, PlainText = param.Payload } }; int numberOfOutputsToSave = 192 / Shift; var indexAtWhichToStartSaving = NUMBER_OF_ITERATIONS - numberOfOutputsToSave; for (var i = 0; i < NumberOfCases; i++) { Debug.WriteLineIf((i + 1) % 10 == 0, $"Running MCT Encryption round {i + 1} out of {NumberOfCases}"); var lastResponse = responses.Last(); var tempText = lastResponse.PlainText.GetDeepCopy(); var tempIv = lastResponse.IV.GetDeepCopy(); BitString prevTempIv = null; var lastCipherTexts = new List <BitString>(); BitString output = null; var keysForThisRound = responses[i].Keys; for (var j = 0; j < NUMBER_OF_ITERATIONS; j++) { prevTempIv = tempIv.GetDeepCopy(); output = _algo.ProcessPayload(new ModeBlockCipherParameters( BlockCipherDirections.Encrypt, tempIv, keysForThisRound, tempText )).Result; tempText = prevTempIv.MSBSubstring(0, Shift); if (j >= indexAtWhichToStartSaving) { lastCipherTexts.Insert(0, output.GetDeepCopy()); } } lastResponse.CipherText = output; responses.Add(new AlgoArrayResponse() { Keys = _keyMaker.MixKeys(new TDESKeys(lastResponse.Keys.GetDeepCopy()), lastCipherTexts).ToOddParityBitString(), PlainText = prevTempIv.GetDeepCopy().MSBSubstring(0, Shift), IV = tempIv.GetDeepCopy() }); } responses.RemoveAt(responses.Count() - 1); return(new Common.Symmetric.MCTResult <AlgoArrayResponse>(responses)); }
public BitString PolyVal(BitString H, BitString X) { var invX = new BitString(0); for (var i = 0; i < X.BitLength / 128; i++) { invX = invX.ConcatenateBits(LittleEndianify(X.MSBSubstring(128 * i, 128))); } var reversedH = LittleEndianify(H); var invH = MulXGHash(reversedH); var gHash = _gcmInternals.GHash(invH, invX); return(LittleEndianify(gHash)); }
/// <summary> /// Sponge function for Keccak. Gathers content for sponge and performs hash /// </summary> /// <param name="message">Raw BitString message</param> /// <param name="digestSize">Digest Size</param> /// <param name="capacity">Capacity of the sponge function</param> /// <returns>Message digest</returns> public static BitString Sponge(BitString message, int digestSize, int capacity) { // Define properties // All possible rates are divisible by 8 var rate = _b - capacity; // Pad the message var paddedMessage = PadMessage(message, rate); // Split up padded message into rate chunks var n = paddedMessage.BitLength / rate; var P = new BitString[n]; for (var i = 0; i < n; i++) { P[i] = BitString.MSBSubstring(paddedMessage, i * rate, rate); } // Build sponge var sponge = new BitString(_b); for (var i = 0; i < n; i++) { var P_i = ConvertEndianness(P[i]); var spongeContent = BitString.XOR(sponge, BitString.ConcatenateBits(P_i, new BitString(capacity))); sponge = Keccak_p(spongeContent); } // Truncate output var Z = new BitString(0); while (true) { Z = BitString.ConcatenateBits(Z, BitString.MSBSubstring(sponge, 0, rate)); if (digestSize <= Z.BitLength) { return(LittleEndianSubstring(Z, 0, digestSize)); } sponge = Keccak_p(sponge); } }
public FfcSignatureResult Sign(FfcDomainParameters domainParameters, FfcKeyPair keyPair, BitString message, bool skipHash = false) { BigInteger r, s; do { var k = _entropyProvider.GetEntropy(1, domainParameters.Q - 1); var kInv = k.ModularInverse(domainParameters.Q); r = BigInteger.ModPow(domainParameters.G, k, domainParameters.P) % domainParameters.Q; var zLen = System.Math.Min(Sha.HashFunction.OutputLen, new BitString(domainParameters.Q).BitLength); var z = BitString.MSBSubstring(Sha.HashMessage(message).Digest, 0, zLen).ToPositiveBigInteger(); s = (kInv * (z + keyPair.PrivateKeyX * r)) % domainParameters.Q; } while (r == 0 || s == 0); return(new FfcSignatureResult(new FfcSignature(r, s))); }
public KeccakState(BitString content, int b) // b is always 1600 but keep it flexible for future { Width = b / GridSize; L = (int)System.Math.Log(Width, 2); _state = new ulong[RowSize, ColSize]; // done for better speed when using b as 1600 if (b == 1600) { _offsets = new int[5, 5] { { 0, 36, 3, 41, 18 }, { 1, 44, 10, 45, 2 }, { 62, 6, 43, 15, 61 }, { 28, 55, 25, 21, 56 }, { 27, 20, 39, 8, 14 } }; } else { _offsets = new int[5, 5]; int x = 1, y = 0; for (var t = 0; t < 24; t++) { _offsets[x, y] = ((t + 1) * (t + 2) / 2) % Width; var newX = (0 * x + 1 * y) % 5; var newY = (2 * x + 3 * y) % 5; x = newX; y = newY; } } for (var x = 0; x < RowSize; x++) { for (var y = 0; y < ColSize; y++) { _state[x, y] = BitStringToLong(content.MSBSubstring((x + RowSize * y) * Width, Width)); } } }
// Use this method when you need a Little Endian substring that is not a multiple of 8 bits in length // For the last byte, we would need to pull bits from the other end of the byte, rather than like reading an array in order // This only occurs once under SHAKE with variable output sizes private static BitString LittleEndianSubstring(BitString message, int startIdx, int length) { var lastFullByte = (length / 8) * 8; // Integer division rounds down for us var firstBytes = BitString.MSBSubstring(message, startIdx, lastFullByte); if (length == lastFullByte) { return(firstBytes); } var nextByte = BitString.MSBSubstring(message, startIdx + lastFullByte, 8); var bitsNeeded = length % 8; var lastBits = new BitString(0); if (bitsNeeded != 0) { lastBits = BitString.Substring(nextByte, 0, bitsNeeded); } return(BitString.ConcatenateBits(firstBytes, lastBits)); }
public static BitString[] TriPartitionBitString(BitString bitString) { //string needs to be evenly splittable into three parts, and be on the byte boundary. 3 * 8 = 24 if (bitString.BitLength % (PARTITIONS * BITS_IN_BYTE) != 0) { throw new Exception($"Can't tripartition a bitstring of size {bitString.BitLength}"); } var retVal = new BitString[PARTITIONS]; for (var i = 0; i < PARTITIONS; i++) { retVal[i] = new BitString(0); } for (var i = 0; i < bitString.BitLength / BLOCK_SIZE_BITS; i++) { var ptIndex = i % PARTITIONS; retVal[ptIndex] = retVal[ptIndex].ConcatenateBits(bitString.MSBSubstring(i * BLOCK_SIZE_BITS, BLOCK_SIZE_BITS)); } return(retVal); }
public BitString AesCtr(BitString key, BitString initialCounterBlock, BitString input) { var ecb = _factory.GetStandardCipher(_engine, BlockCipherModesOfOperation.Ecb); var block = initialCounterBlock.GetDeepCopy(); var output = new BitString(0); var iterations = (int)System.Math.Ceiling(input.BitLength / 128.0); for (var i = 0; i < iterations; i++) { var inputBlock = (i * 128 + 128 <= input.BitLength) ? input.MSBSubstring(i * 128, 128) : input.MSBSubstring(i * 128, input.BitLength % 128); if (block.BitLength != 128) { throw new Exception($"\nBlock length is not a mulitple of 128.\nInput: {input.ToHex()}\nKey: {key.ToHex()}\nInitialCtr: {initialCounterBlock.ToHex()}"); } var keyStreamBlock = ecb.ProcessPayload ( new ModeBlockCipherParameters ( BlockCipherDirections.Encrypt, key, block ) ); var beginOfBlock = block.MSBSubstring(0, 32); var endOfBlock = block.MSBSubstring(32, 96); block = beginOfBlock.BitStringAddition(new BitString("01000000")).ConcatenateBits(endOfBlock).Substring(0, 128); var inputXor = inputBlock.GetDeepCopy().ConcatenateBits(BitString.Zeroes(keyStreamBlock.Result.BitLength - inputBlock.BitLength)); var xor = keyStreamBlock.Result.XOR(inputXor).MSBSubstring(0, inputBlock.BitLength); output = output.ConcatenateBits(xor); } return(output); }
public HssVerificationResult VerifyHssSignature(BitString msg, BitString publicKey, BitString signature) { // 1. The signature S is parsed into its components as follows: // a. Nspk = strTou32(first four bytes of S) // if Nspk+1 is not equal to the number of levels L in pub return INVALID var Nspk = (int)signature.MSBSubstring(0, 32).ToPositiveBigInteger(); var lengthInPublic = (int)publicKey.MSBSubstring(0, 32).ToPositiveBigInteger(); if (Nspk + 1 != lengthInPublic) { return(new HssVerificationResult("Validation failed. L values do not match.")); } // b. for (i = 0; i<Nspk; i = i + 1) { // siglist[i] = next LMS signature parsed from S // publist[i] = next LMS public key parsed from S // } var siglist = new BitString[Nspk + 1]; var publist = new BitString[Nspk + 1]; var currIndex = 32; for (int i = 0; i < Nspk; i++) { // assume sig and pub have same LMS mode var otsCode = signature.MSBSubstring(currIndex + 32, 32); var n = LmotsModeMapping.GetNFromCode(otsCode); var p = LmotsModeMapping.GetPFromCode(otsCode); var sigtype = signature.MSBSubstring((8 + n * (p + 1)) * 8 + currIndex, 32); var m = LmsModeMapping.GetMFromCode(sigtype); var h = LmsModeMapping.GetHFromCode(sigtype); var siglen = (12 + n * (p + 1) + m * h) * 8; var publen = 192 + (m * 8); siglist[i] = signature.MSBSubstring(currIndex, siglen); currIndex += siglen; publist[i] = signature.MSBSubstring(currIndex, publen); currIndex += publen; } // c. siglist[Nspk] = next LMS signature parsed from S var otsCodeLast = signature.MSBSubstring(currIndex + 32, 32); var nLast = LmotsModeMapping.GetNFromCode(otsCodeLast); var pLast = LmotsModeMapping.GetPFromCode(otsCodeLast); var sigtypeLast = signature.MSBSubstring((8 + nLast * (pLast + 1)) * 8 + currIndex, 32); var mLast = LmsModeMapping.GetMFromCode(sigtypeLast); var hLast = LmsModeMapping.GetHFromCode(sigtypeLast); var siglenLast = (12 + nLast * (pLast + 1) + mLast * hLast) * 8; siglist[Nspk] = signature.MSBSubstring(currIndex, siglenLast); // 2. Verify each part of the signature var key = publicKey.MSBSubstring(32, publicKey.BitLength - 32); for (int i = 0; i < Nspk; i++) { var result = _lms[i].VerifyLmsSignature(publist[i], key, siglist[i]); if (!result.Success) { return(new HssVerificationResult("LMS Validation failed: " + result.ErrorMessage)); } key = publist[i]; } // 3. return lms_verify(message, key, siglist[Nspk]) var finalResult = _lms[Nspk].VerifyLmsSignature(msg, key, siglist[Nspk]); if (finalResult.Success) { return(new HssVerificationResult()); } else { return(new HssVerificationResult("Validation failed. Final check failed: " + finalResult.ErrorMessage)); } }
private VerifyResult EmsaPssVerify(BitString M, BitString EM, int emBits) { var mHash = Sha.HashMessage(M).Digest; if (EM.BitLength < mHash.BitLength / 8 + SaltLength + 2) { return(new VerifyResult("RSA PSS Verify: inconsistent result")); } if (!EM.Substring(0, 8).Equals(Bc)) { return(new VerifyResult("RSA PSS Verify: 'BC' hex not found")); } // Bit values var maskedDB = EM.MSBSubstring(0, EM.BitLength - mHash.BitLength - 8); var H = EM.MSBSubstring(maskedDB.BitLength, mHash.BitLength); if (!maskedDB.MSBSubstring(0, EM.BitLength - emBits).Equals(BitString.Zeroes(EM.BitLength - emBits))) { return(new VerifyResult("RSA PSS Verify: Leading 0s not found in maskedDB")); } var dbMask = Mask.Mask(H, EM.BitLength - mHash.BitLength - 8); var DB = BitString.XOR(maskedDB, dbMask); for (var i = 0; i < EM.BitLength - emBits; i++) { DB.Set(DB.BitLength - i - 1, false); } var leftmostOctets = EM.BitLength - mHash.BitLength - SaltLength * 8 - 16; if (leftmostOctets != 0) { if (!DB.MSBSubstring(0, leftmostOctets).Equals(BitString.Zeroes(leftmostOctets))) { return(new VerifyResult("RSA PSS Verify: DB incorrect, improper number of leading 0s")); } } if (!DB.MSBSubstring(leftmostOctets, 8).Equals(ZeroOne)) { return(new VerifyResult("RSA PSS Verify: DB incorrect, '01' byte not found")); } var salt = DB.Substring(0, SaltLength * 8); var MPrime = BitString.Zeroes(64); MPrime = BitString.ConcatenateBits(MPrime, mHash); MPrime = BitString.ConcatenateBits(MPrime, salt); var HPrime = Sha.HashMessage(MPrime).Digest; if (HPrime.Equals(H)) { return(new VerifyResult()); } else { return(new VerifyResult("RSA PSS Verify: Hashes do not match")); } }
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)); }
public LmsVerificationResult VerifyLmsSignature(BitString msg, BitString publicKey, BitString signature) { // 1. If the public key is not at least eight bytes long, return INVALID. if (publicKey.BitLength < 64) { return(new LmsVerificationResult("Validation failed. Public key wrong length.")); } // 2. Parse pubtype, I, and T[1] from the public key as follows: // a. pubtype = strTou32(first 4 bytes of public key) var pubType = publicKey.MSBSubstring(0, 32); // b. ots_typecode = strTou32(next 4 bytes of public key) var ots_typecode = publicKey.MSBSubstring(32, 32); // c. Set m according to pubtype, based on Table 2. var m = LmsModeMapping.GetMFromCode(pubType); // d. If the public key is not exactly 24 + m bytes long, return INVALID. if (publicKey.BitLength != (24 + m) * 8) { return(new LmsVerificationResult("Validation failed. Public key wrong length.")); } // e. I = next 16 bytes of the public key var I = publicKey.MSBSubstring(64, 128); // f. T[1] = next m bytes of the public key var root = publicKey.MSBSubstring(192, m * 8); // 3. Compute the LMS Public Key Candidate Tc from the signature, message, identifier, // pubtype, and ots_typecode, using Algorithm 6a. // Algorithm 6a: // 1. If the signature is not at least eight bytes long, return INVALID. if (signature.BitLength < 64) { return(new LmsVerificationResult("Validation failed. Signature wrong length.")); } // 2. Parse sigtype, q, lmots_signature, and path from the signature as follows: // a. q = strTou32(first 4 bytes of signature) var q = signature.MSBSubstring(0, 32); // b. otssigtype = strTou32(next 4 bytes of signature) var otssigtype = signature.MSBSubstring(32, 32); // c. If otssigtype is not the OTS typecode from the public key, return INVALID. if (!otssigtype.Equals(ots_typecode)) { return(new LmsVerificationResult("Validation failed. OTS Code incongruent.")); } // d. Set n, p according to otssigtype and Table 1; if the signature is not // at least 12 + n* (p + 1) bytes long, return INVALID. var n = LmotsModeMapping.GetNFromCode(otssigtype); var p = LmotsModeMapping.GetPFromCode(otssigtype); if (signature.BitLength < (12 + n * (p - 1)) * 8) { return(new LmsVerificationResult("Validation failed. Signature wrong length.")); } // e. lmots_signature = bytes 4 through 7 + n* (p + 1) of signature var lmots_signature = signature.MSBSubstring(32, (4 + n * (p + 1)) * 8); // f. sigtype = strTou32(bytes 8 + n* (p + 1)) through 11 + n* (p + 1) of signature) var sigtype = signature.MSBSubstring((8 + n * (p + 1)) * 8, 32); // g. If sigtype is not the LM typecode from the public key, return INVALID. if (!sigtype.Equals(pubType)) { return(new LmsVerificationResult("Verification failed. Type mismatch.")); } // h. Set m, h according to sigtype and Table 2. // m already set from above var h = LmsModeMapping.GetHFromCode(sigtype); // i. If q >= 2^h or the signature is not exactly 12 + n* (p + 1) + m* h bytes long, return INVALID. if (q.ToPositiveBigInteger() >= (1 << h) || signature.BitLength != (12 + n * (p + 1) + m * h) * 8) { return(new LmsVerificationResult("Verification failed. Signature wrong length.")); } // j. Set path as follows: // path[0] = next m bytes of signature // path[1] = next m bytes of signature // ... // path[h-1] = next m bytes of signature var path = new BitString[h]; for (int i = 0; i < h; i++) { path[i] = signature.MSBSubstring(((12 + n * (p + 1)) * 8) + (i * m * 8), m * 8); } // 3. Kc = candidate public key computed by applying Algorithm 4b to the signature lmots_signature, // the message, and the identifiers I, q var Kc = _lmots.Algorithm4b(lmots_signature, msg, otssigtype, I, q); if (Kc == null) { return(new LmsVerificationResult("Verification failed. Algorithm 4b failed.")); } // 4. Compute the candidate LMS root value Tc as described in rfc 8554 var node_num = (1 << h) + q.ToPositiveBigInteger(); var tmp = _sha256.HashMessage(I .ConcatenateBits(new BitString(node_num, 32)) .ConcatenateBits(D_LEAF) .ConcatenateBits(Kc)).Digest; for (int i = 0; node_num > 1; node_num /= 2) { if (node_num % 2 == 1) { tmp = _sha256.HashMessage(I .ConcatenateBits(new BitString(node_num / 2, 32)) .ConcatenateBits(D_INTR) .ConcatenateBits(path[i]) .ConcatenateBits(tmp)).Digest; } else { tmp = _sha256.HashMessage(I .ConcatenateBits(new BitString(node_num / 2, 32)) .ConcatenateBits(D_INTR) .ConcatenateBits(tmp) .ConcatenateBits(path[i])).Digest; } i++; } // 5. Return Tc var Tc = tmp; // END Algorithm 6a // 4. If Tc is equal to T[1], return VALID; otherwise, return INVALID. if (Tc.Equals(root)) { return(new LmsVerificationResult()); } else { return(new LmsVerificationResult("Verification failed. Signature invalid.")); } }
/* * INPUT: The initial Msg is the length of the digest size * * MCT(Msg, MaxOutLen, MinOutLen, OutLenIncrement) * { * Range = (MaxOutLen – MinOutLen + 1); * OutputLen = MaxOutLen; * FunctionName = ""; * 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] = CSHAKE(InnerMsg, OutputLen, FunctionName, Customization); * Rightmost_Output_bits = Right(Output[i], 16); * OutputLen = MinOutLen + (floor((Rightmost_Output_bits % Range) / OutLenIncrement) * OutLenIncrement); * Customization = BitsToString(InnerMsg || Rightmost_Output_bits); * } * * OutputJ[j] = Output[1000]; * } * * return OutputJ; * } */ #endregion MonteCarloAlgorithm Pseudocode public MctResult <AlgoArrayResponseWithCustomization> MCTHash(HashFunction function, BitString message, MathDomain domain, bool customizationHex, bool isSample) { _customizationHex = customizationHex; if (isSample) { NUM_OF_RESPONSES = 3; } var responses = new List <AlgoArrayResponseWithCustomization>(); var i = 0; var j = 0; var min = domain.GetDomainMinMax().Minimum; var max = domain.GetDomainMinMax().Maximum; var increment = domain.GetDomainMinMax().Increment; //var outputLen = (int)System.Math.Floor((double)max / 8) * 8; var outputLen = max; var customization = ""; var functionName = ""; 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; 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)); innerMessage = BitString.MSBSubstring(innerMessage, 0, 128); function.DigestLength = outputLen; var innerResult = _iCSHAKE.HashMessage(function, innerMessage, customization, functionName); innerDigest = innerResult.Digest.GetDeepCopy(); // Will always have 16 bits to pull from var rightmostBitString = BitString.Substring(innerDigest, 0, 16); var rightmostBits = rightmostBitString.Bits; //outputLen = min + (8 * rightmostBits.ToInt()) % range; outputLen = min + (int)System.Math.Floor((double)(rightmostBits.ToInt() % range) / increment) * increment; 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 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")); } }
public SharedSecretResponse Decrypt(KeyPair rsaKeyPair, BitString ciphertext, BitString additionalInput) { if (additionalInput == null) { additionalInput = new BitString(0); } // 1. Initializations: // a. nLen = the byte length of n. For this Recommendation, nLen ≥ 256. var nLenBits = rsaKeyPair.PubKey.N.ExactBitLength().ValueToMod(BitString.BITSINBYTE); var nLen = nLenBits.CeilingDivide(BitString.BITSINBYTE); var hLenBits = _sha.HashFunction.OutputLen; var HLen = hLenBits.CeilingDivide(BitString.BITSINBYTE); // b. DecryptErrorFlag = False. // 2. Check for erroneous input: // a. If the length of the ciphertext C is not nLen bytes, output an indication of erroneous // input, and exit without further processing. if (ciphertext.BitLength != nLenBits) { throw new DecryptionFailedException("Ciphertext bit length did not match nLen."); } // b. Convert the ciphertext byte string C to a ciphertext integer c // (see Appendix B.2): // c = BS2I(C). var c = ciphertext.ToPositiveBigInteger(); // c. If the ciphertext integer c is not such that 1 < c < (n – 1), output an indication of // erroneous input, and exit without further processing. if (c <= 1 || c >= rsaKeyPair.PubKey.N - 1) { throw new DecryptionFailedException("Ciphertext integer c is not such that 1 < c < (n - 1)."); } // 3. RSA decryption: // a. Apply RSADP (see Section 7.1.2) to the ciphertext integer c using the private key // (n, d) to produce an integer em: // em = RSADP((n, d), c).24 var em = _rsa.Decrypt(c, rsaKeyPair.PrivKey, rsaKeyPair.PubKey).PlainText; // b. Convert the integer em to an encoded message EM, a byte string of nLen bytes (see // Appendix B.1): // EM = I2BS(em, nLen). var EM = new BitString(em).PadToModulusMsb(nLenBits); // 4. OAEP decoding: // a. Apply the selected hash function (see Section 5.1) to compute: // HA = H(A). // HA is a byte string of HLen bytes. var HA = _sha.HashMessage(additionalInput).Digest; // b. Separate the encoded message EM into a single byte Y, a byte string // maskedMGFSeed′ of HLen bytes, and a byte string maskedDB′ of nLen – HLen – 1 // bytes as follows: // EM = Y || maskedMGFSeed′ || maskedDB′. var Y = EM.MSBSubstring(0, BitString.BITSINBYTE); var maskedMGFSeed = EM.MSBSubstring(BitString.BITSINBYTE, hLenBits); var maskedDB = EM.MSBSubstring(BitString.BITSINBYTE + hLenBits, (nLen - HLen - 1) * BitString.BITSINBYTE); // c. Apply the mask-generation function specified in Section 7.2.2.2 to compute: // mgfSeedMask′ = MGF(maskedDB′, HLen). var mgfSeedMask = _mgf.Generate(maskedDB, hLenBits); // d. Let mgfSeed′ = maskedMGFSeed′ ⊕ mgfSeedMask′. var mgfSeed = maskedMGFSeed.XOR(mgfSeedMask); // e. Apply the mask-generation function specified in Section 7.2.2.2 to compute: // dbMask′= MGF(mgfSeed′, nLen – HLen – 1). var dbMask = _mgf.Generate(mgfSeed, (nLen - HLen - 1) * BitString.BITSINBYTE); // f. Let DB′ = maskedDB′ ⊕ dbMask′. var DB = maskedDB.XOR(dbMask); // g. Separate DB′ into a byte string HA′ of HLen bytes and a byte string X of nLen – // 2HLen – 1 bytes as follows: // DB′ = HA′ || X. var HA2 = DB.MSBSubstring(0, hLenBits); var X = DB.MSBSubstring(hLenBits, (nLen - 2 * HLen - 1) * BitString.BITSINBYTE); // 5. Check for RSA-OAEP decryption errors: // a. DecryptErrorFlag = False. // b. If Y is not the 00 byte (i.e., the bit string 00000000), then DecryptErrorFlag = True. if (Y.ToPositiveBigInteger() != BigInteger.Zero) { throw new DecryptionFailedException("Y did not equal zero."); } // c. If HA′ does not equal HA, then DecryptErrorFlag = True. if (!HA.Equals(HA2)) { throw new DecryptionFailedException("HA` did not equal HA."); } // d. If X does not have the form PS || 00000001 || K, where PS consists of zero or more // consecutive 00 bytes, then DecryptErrorFlag = True. var kStartByte = 0; for (var i = 0; i < X.BitLength.CeilingDivide(8); i++) { if (X[i] == 0x00) { continue; } if (X[i] == 0x01) { kStartByte = i + 1; break; } throw new DecryptionFailedException("X did not have the form PS || 00000001 || K, where PS consists of zero or more consecutive 00 bytes"); } var K = X.MSBSubstring(kStartByte * BitString.BITSINBYTE, X.BitLength - kStartByte * BitString.BITSINBYTE); return(new SharedSecretResponse(K)); }
/* * INPUT: The initial Single-Tuple of a random length between 0 and 65536 bits. * * MCT(Tuple, MaxOutLen, MinOutLen, OutLenIncrement) * { * Range = (MaxOutLen – MinOutLen + 1); * OutputLen = MaxOutLen; * Customization = ""; * * T[0][0] = Tuple; * * for (j = 0; j < 100; j++) * { * for (i = 1; i < 1001; i++) * { * workingBits = Left(T[i-1][0] || ZeroBits(288), 288); * tupleSize = Left(workingBits, 3) % 4 + 1; // never more than 4 tuples to a round * for (k = 0; k < tupleSize; k++) * { * T[i][k] = Substring of workingBits from (k * 288 / tupleSize) to ((k+1) * 288 / tupleSize - 1); * } * Output[i] = TupleHash(T[i], OutputLen, Customization); * Rightmost_Output_bits = Right(Output[i], 16); * OutputLen = MinOutLen + (floor((Rightmost_Output_bits % Range) / OutLenIncrement) * OutLenIncrement); * Customization = BitsToString(T[i][0] || Rightmost_Output_bits); * } * * OutputJ[j] = Output[1000]; * } * * return OutputJ; * } */ #endregion MonteCarloAlgorithm Pseudocode public MCTResultTuple <AlgoArrayResponse> MCTHash(HashFunction function, IEnumerable <BitString> tuple, MathDomain domain, bool hexCustomization, bool isSample) { _hexCustomization = hexCustomization; if (isSample) { NUM_OF_RESPONSES = 3; } var responses = new List <AlgoArrayResponse>(); var i = 0; var j = 0; var min = domain.GetDomainMinMax().Minimum; var max = domain.GetDomainMinMax().Maximum; var increment = domain.GetDomainMinMax().Increment; var minBytes = min / 8; var maxBytes = max / 8; var outputLen = max; var customization = ""; var range = (max - min) + 1; var innerTuple = GetDeepCopy(tuple); try { for (i = 0; i < NUM_OF_RESPONSES; i++) { var innerDigest = new BitString(0); var iterationResponse = new AlgoArrayResponse() { }; iterationResponse.Tuple = innerTuple; iterationResponse.Customization = customization; for (j = 0; j < 1000; j++) { // Might not have 144 bits to pull from so we pad with 0 var innerBitString = BitString.ConcatenateBits(innerTuple.ElementAt(0), BitString.Zeroes(288)) .GetMostSignificantBits(288); var innerTupleSize = innerBitString.GetMostSignificantBits(3).Bits.ToInt() % 4 + 1; innerTuple = new List <BitString>(); for (int k = 0; k < innerTupleSize; k++) { innerTuple.Add(BitString.MSBSubstring(innerBitString, k * 288 / innerTupleSize, 288 / innerTupleSize)); } function.DigestLength = outputLen; var innerResult = _iTupleHash.HashMessage(function, innerTuple, customization); innerDigest = innerResult.Digest.GetDeepCopy(); // Will always have 16 bits to pull from var rightmostBitString = BitString.Substring(innerDigest, 0, 16); var rightmostBits = rightmostBitString.Bits; outputLen = min + (int)System.Math.Floor((double)(rightmostBits.ToInt() % range) / increment) * increment; customization = GetStringFromBytes(BitString.ConcatenateBits(innerTuple.ElementAt(0), rightmostBitString).ToBytes()); innerTuple = new List <BitString>(); innerTuple.Add(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 MCTResultTuple <AlgoArrayResponse>($"{ex.Message}; {outputLen}")); } return(new MCTResultTuple <AlgoArrayResponse>(responses)); }
/* * INPUT: The initial Msg of 128 bits long * * Initial Outputlen = (floor(maxoutlen/8) )*8 * //makes maxoutlen a multiple of 8 and remains within the range specified. * * { * Output0 = Msg; * for (j=0; j<100; j++) { * for (i=1; i<1001; i++) { * M[i] = 128 leftmost bits of Output[i-1]; * Output[i] = SHAKE(M[i],Outputlen); * If (i == 1000){ * Outputlen[j] = Outputlen; * } * Rightmost_Output_bits = rightmost 16 bits of Output[i]; * Range = (maxoutbytes – minoutbytes + 1); * Outputlen = minoutbytes + (Rightmost_Output_bits mod Range); * } * Output[j] = Output[1000]; * OUTPUT: Outputlen[j], Output[j] * } * } */ #endregion MonteCarloAlgorithm Pseudocode public MctResult <AlgoArrayResponse> MctHash(BitString message, MathDomain domain, bool isSample = false) { if (isSample) { NUM_OF_RESPONSES = 3; } var responses = new List <AlgoArrayResponse>(); var i = 0; var j = 0; var min = domain.GetDomainMinMax().Minimum; var max = domain.GetDomainMinMax().Maximum; var minBytes = min / 8; var maxBytes = max / 8; var outputLen = (int)System.Math.Floor((double)max / 8) * 8; var range = (max - min) + 8; //var range = (max - min) + min; var innerMessage = message.GetDeepCopy(); // Might not have 128 bits to pull from so we pad with 0 innerMessage = BitString.ConcatenateBits(innerMessage, BitString.Zeroes(128)); innerMessage = BitString.MSBSubstring(innerMessage, 0, 128); try { for (i = 0; i < NUM_OF_RESPONSES; i++) { var innerDigest = new BitString(0); var iterationResponse = new AlgoArrayResponse() { }; iterationResponse.Message = innerMessage; for (j = 0; j < 1000; j++) { var innerResult = _sha.HashMessage(innerMessage, outputLen); innerDigest = innerResult.Digest.GetDeepCopy(); // Will always have 16 bits to pull from var rightmostBits = BitString.Substring(innerDigest, 0, 16).Bits; outputLen = min + (8 * GetIntFromBits(rightmostBits)) % range; innerMessage = innerDigest.GetDeepCopy(); // Might not have 128 bits to pull from so we pad with 0 innerMessage = BitString.ConcatenateBits(innerMessage, BitString.Zeroes(128)); innerMessage = BitString.MSBSubstring(innerMessage, 0, 128); } iterationResponse.Digest = innerDigest.GetDeepCopy(); responses.Add(iterationResponse); } } catch (Exception ex) { ThisLogger.Debug($"i count {i}, j count {j}"); ThisLogger.Error(ex); return(new MctResult <AlgoArrayResponse>($"{ex.Message}; {outputLen}")); } return(new MctResult <AlgoArrayResponse>(responses)); }
public MCTResult <AlgoArrayResponse> Encrypt(IModeBlockCipherParameters param) { var ivs = TdesPartitionHelpers.SetupIvs(param.Iv); var responses = new List <AlgoArrayResponse> { new AlgoArrayResponse { IV = ivs[0], Keys = param.Key, PlainText = param.Payload } }; var numberOfOutputsToSave = 192 / Shift; var indexAtWhichToStartSaving = NUMBER_OF_ITERATIONS - numberOfOutputsToSave; for (var i = 0; i < NumberOfCases; i++) { ivs = TdesPartitionHelpers.SetupIvs(responses[i].IV.GetDeepCopy()); var tempText = responses[i].PlainText.GetDeepCopy(); BitString prevTempIv = null; var tempIv = responses[i].IV.GetDeepCopy(); var keysForThisRound = responses[i].Keys; BitString output = null; var holdouts = new BitString[3]; var lastCipherTexts = new List <BitString>(); for (var j = 0; j < NUMBER_OF_ITERATIONS; j++) { switch (j) { case 0: tempIv = ivs[0].GetDeepCopy(); break; case 1: tempIv = ivs[1].GetDeepCopy(); break; case 2: tempIv = ivs[2].GetDeepCopy(); break; default: tempIv = prevTempIv.MSBSubstring(Shift, 64 - Shift).ConcatenateBits(holdouts[2]); break; } prevTempIv = tempIv.GetDeepCopy(); output = _algo.ProcessPayload(new ModeBlockCipherParameters( BlockCipherDirections.Encrypt, tempIv, keysForThisRound, tempText) ).Result; holdouts[2] = holdouts[1]; holdouts[1] = holdouts[0]; holdouts[0] = output; tempText = prevTempIv.MSBSubstring(0, Shift); if (j >= indexAtWhichToStartSaving) { lastCipherTexts.Insert(0, output.GetDeepCopy()); } } responses[i].CipherText = output; var newIv = prevTempIv.MSBSubstring(Shift, 64 - Shift).ConcatenateBits(output); var newIvs = TdesPartitionHelpers.SetupIvs(newIv); responses.Add(new AlgoArrayResponse() { Keys = _keyMaker.MixKeys(new TDESKeys(responses[i].Keys.GetDeepCopy()), lastCipherTexts.ToList()) .ToOddParityBitString(), PlainText = prevTempIv.GetDeepCopy().MSBSubstring(0, Shift), IV = newIvs[0] }); } responses.RemoveAt(responses.Count - 1); return(new MCTResult <AlgoArrayResponse>(responses)); }