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 OtherInfo( IEntropyProvider entropyProvider, string otherInfoPattern, int otherInfoLength, KeyAgreementRole thisPartyKeyAgreementRole, PartyOtherInfo thisPartyOtherInfo, PartyOtherInfo otherPartyOtherInfo ) { _thisPartyKeyAgreementRole = thisPartyKeyAgreementRole; _thisPartyOtherInfo = thisPartyOtherInfo; _otherPartyOtherInfo = otherPartyOtherInfo; // split the pattern into pieces var pieces = otherInfoPattern.Split("||".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); foreach (var piece in pieces) { var workingPiece = piece.Replace("||", ""); _otherInfo = _otherInfo.ConcatenateBits(ConcatenatePieceOntoOtherInfo(workingPiece)); } // Add entropy to hit otherInfoLength _otherInfo = _otherInfo.ConcatenateBits(entropyProvider.GetEntropy(otherInfoLength - _otherInfo.BitLength)); _otherInfo = _otherInfo.GetMostSignificantBits(otherInfoLength); }
public override SymmetricCipherResult ProcessPayload(IModeBlockCipherParameters param) { CheckPayloadRequirements(param.Payload); var key = param.Key.ToBytes(); var engineParam = new EngineInitParameters(param.Direction, key, param.UseInverseCipherMode); _engine.Init(engineParam); var numberOfBlocks = GetNumberOfBlocks(param.Payload.BitLength); var outBuffer = GetOutputBuffer(param.Payload.BitLength); if (param.Direction == BlockCipherDirections.Encrypt) { Encrypt(param, numberOfBlocks, outBuffer); } else { Decrypt(param, numberOfBlocks, outBuffer); } var output = new BitString(outBuffer); return(new SymmetricCipherResult(output.GetMostSignificantBits(param.Payload.BitLength))); }
public KdfResult DeriveKey(IAns942Parameters param) { if (!(param is ConcatAns942Parameters concatParams)) { return(new KdfResult("Unable to parse concat parameters")); } if (concatParams.KeyLen <= 0 || concatParams.KeyLen > 65536) { return(new KdfResult($"KeyLen must be between [1, 65536]. Value given was: {concatParams.KeyLen}")); } var d = (int)System.Math.Ceiling(concatParams.KeyLen / (decimal)_sha.HashFunction.OutputLen); var counter = BitString.To32BitString(1); var h = new BitString(0); for (var i = 1; i <= d; i++) { // H[i] = Hash(ZZ || counter || otherInfo) var hashInput = concatParams.Zz.ConcatenateBits(counter).ConcatenateBits(concatParams.OtherInfo); h = h.ConcatenateBits(_sha.HashMessage(hashInput).Digest); counter = counter.BitStringAddition(BitString.One()); } return(new KdfResult(h.GetMostSignificantBits(concatParams.KeyLen))); }
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), ""); }
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()); }
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)); } }
public KdfResult DeriveKey(IAns942Parameters param) { if (!(param is DerAns942Parameters derParams)) { return(new KdfResult("Unable to parse der parameters")); } if (derParams.KeyLen <= 0 || derParams.KeyLen > 65536) { return(new KdfResult($"KeyLen must be between [1, 65536]. Value given was: {derParams.KeyLen}")); } var d = (int)System.Math.Ceiling(derParams.KeyLen / (decimal)_sha.HashFunction.OutputLen); var h = new BitString(0); var counter = BitString.To32BitString(0); for (var i = 1; i <= d; i++) { // Increment Counter counter = counter.BitStringAddition(BitString.One()); // Prepare ANS.1/DER encoded OtherInfo var derEncodedOtherInfo = DerEncode(derParams, counter); var str = derEncodedOtherInfo.ToHex(); // H[i] = Hash(ZZ || otherInfo) h = h.ConcatenateBits(_sha.HashMessage(derParams.Zz.ConcatenateBits(derEncodedOtherInfo)).Digest); } return(new KdfResult(h.GetMostSignificantBits(derParams.KeyLen))); }
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)); }
// Question: Is it a hard restriction that the hash within HMAC is the same used within the signature process? public BigInteger GetNonce(BigInteger privateD, BigInteger hashedMessage, BigInteger orderN) { // 1.3 var seedMaterial = new BitString(privateD).PadToModulusMsb(32).ConcatenateBits(new BitString(hashedMessage).PadToModulusMsb(32)); // 1.4 var key = BitString.Zeroes(_hmac.OutputLength); // 1.5 var v = _01bits.GetMostSignificantBits(_hmac.OutputLength); // 1.6 key = _hmac.Generate(key, v.ConcatenateBits(BitString.ConcatenateBits(BitString.Zeroes(8), seedMaterial))).Mac; // 1.7 v = _hmac.Generate(key, v).Mac; // 1.8 key = _hmac.Generate(key, v.ConcatenateBits(BitString.ConcatenateBits(new BitString("01"), seedMaterial))).Mac; // 1.9 v = _hmac.Generate(key, v).Mac; // 2 var nlen = orderN.ExactBitLength(); // 3 BigInteger k = 0; while (k == 0 || k >= orderN) { // 4.1 var tmp = new BitString(0); // 4.2 while (tmp.BitLength < nlen) { v = _hmac.Generate(key, v).Mac; tmp = tmp.ConcatenateBits(v); } // 4.3 k = tmp.GetMostSignificantBits(nlen).ToPositiveBigInteger(); // 4.4 if (k > 0 && k < orderN) { return(k); } // 4.5 key = _hmac.Generate(key, v.ConcatenateBits(BitString.Zeroes(8))).Mac; // 4.6 v = _hmac.Generate(key, v).Mac; } return(k); }
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)); }
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)); }
private static void AllTransform(List <AlgoArrayResponse> results) { // CFB1 - PT is always "0" (hex), CT is the most significant bit of the normal KAT. results.ForEach(fe => { fe.PlainText = new BitString("00", 1); fe.CipherText = BitString.GetMostSignificantBits(1, fe.CipherText); }); }
public void ShouldEncryptDecryptToSameValue(string label, BitString iv, BitString pt, BitString key, BitString ct) { var encryptResult = _subjectCs3 .ProcessPayload(new ModeBlockCipherParameters(BlockCipherDirections.Encrypt, iv.GetDeepCopy(), key, pt)).Result; var decryptResult = _subjectCs3 .ProcessPayload(new ModeBlockCipherParameters(BlockCipherDirections.Decrypt, iv.GetDeepCopy(), key, encryptResult)).Result; Assert.AreEqual(pt.GetMostSignificantBits(pt.BitLength).ToHex(), decryptResult.GetMostSignificantBits(pt.BitLength).ToHex()); }
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)); }
private MCTResult <AlgoArrayResponse> Encrypt(IModeBlockCipherParameters param) { List <AlgoArrayResponse> responses = new List <AlgoArrayResponse>(); int i = 0; int j = 0; try { for (i = 0; i < 100; i++) { AlgoArrayResponse iIterationResponse = new AlgoArrayResponse() { IV = param.Iv, Key = param.Key, PlainText = param.Payload }; BitString jCipherText = null; BitString previousCipherText = null; BitString copyPreviousCipherText = null; var ivCopiedBytes = iIterationResponse.IV.ToBytes(); param.Iv = new BitString(ivCopiedBytes); for (j = 0; j < 1000; j++) { var jResult = _algo.ProcessPayload(param); jCipherText = jResult.Result; if (j == 0) { previousCipherText = iIterationResponse.IV.ConcatenateBits(jCipherText.GetMostSignificantBits(param.Payload.BitLength - param.Iv.BitLength)); } param.Payload = previousCipherText; copyPreviousCipherText = previousCipherText; previousCipherText = jCipherText; } iIterationResponse.CipherText = jCipherText; responses.Add(iIterationResponse); param.Key = _keyMaker.MixKeys(param.Key, previousCipherText, copyPreviousCipherText); param.Iv = previousCipherText.GetMostSignificantBits(param.Iv.BitLength); } } 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)); }
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)); }
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(); }
public KdfResult Kdf(KdfParameterIkeV1 param, BitString fixedInfo = null) { var hashFunction = ShaAttributes.GetHashFunctionFromEnum(param.HashFunction); var kdf = _ikeV1Factory.GetIkeV1Instance(AuthenticationMethods.Dsa, hashFunction); var result = kdf.GenerateIke(param.InitiatorEphemeralData, param.ResponderEphemeralData, param.Z, param.AdditionalInitiatorNonce, param.AdditionalResponderNonce, null); var dkm = new BitString(0) .ConcatenateBits(result.SKeyIdD) .ConcatenateBits(result.SKeyIdA) .ConcatenateBits(result.SKeyIdE); return(new KdfResult(dkm.GetMostSignificantBits(param.L))); }
public KdfResult DeriveKey(BitString z, BitString sharedInfo, int keyLength) { var numBlocks = keyLength.CeilingDivide(_hash.HashFunction.OutputLen); var keyData = new BitString(0); for (var i = 1; i <= numBlocks; i++) { var counter = BitString.To32BitString(i); var hashInput = z.ConcatenateBits(counter).ConcatenateBits(sharedInfo); keyData = keyData.ConcatenateBits(_hash.HashMessage(hashInput).Digest); } return(new KdfResult(keyData.GetMostSignificantBits(keyLength))); }
private BitString GenerateKeyingMaterial(BitString key, BitString fixedData, int dkmLength) { var iterations = dkmLength.CeilingDivide(_hmac.OutputLength); var keyingMaterial = new BitString(0); var temp = new BitString(0); for (var i = 0; i < iterations; i++) { var valueI = temp.ConcatenateBits(fixedData).ConcatenateBits(BitString.To32BitString(i + 1).GetLeastSignificantBits(8)); temp = _hmac.Generate(key, valueI).Mac; keyingMaterial = keyingMaterial.ConcatenateBits(temp); } return(keyingMaterial.GetMostSignificantBits(dkmLength)); }
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)); }
private BitString Prf(BitString secret, string label, BitString seed, int outputLength) { var labelBytes = new BitString(Encoding.ASCII.GetBytes(label)); var prfSeed = labelBytes.ConcatenateBits(seed); var numBlocks = outputLength.CeilingDivide(_hmac.OutputLength); var A = prfSeed.GetDeepCopy(); var output = new BitString(0); for (var i = 0; i < numBlocks; i++) { A = _hmac.Generate(secret, A).Mac; output = output.ConcatenateBits(_hmac.Generate(secret, A.ConcatenateBits(prfSeed)).Mac); } return(output.GetMostSignificantBits(outputLength)); }
// 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 Expand(BitString pseudoRandomKey, BitString otherInfo, int keyLengthBytes) { // keyLength comes in as bytes var keyLengthBits = keyLengthBytes * 8; var n = keyLengthBits.CeilingDivide(_hmac.OutputLength); var t = new BitString(0); var counter = new BitString("00"); var result = new BitString(0); for (short i = 1; i <= n; i++) { counter = counter.BitStringAddition(BitString.One()); t = _hmac.Generate(pseudoRandomKey, t.ConcatenateBits(otherInfo).ConcatenateBits(counter)).Mac; result = result.ConcatenateBits(t); } return(result.GetMostSignificantBits(keyLengthBits)); }
private BitString Kdf(int length, BitString key, BitString salt, BitString kdr, BitString index, BitString label) { var keyId = label.ConcatenateBits(Divide(index, kdr)); var m = length.CeilingDivide(128); // guaranteed to be either 1 or 2 // Left pad keyId with 0s so it is the same length as salt keyId = BitString.Zeroes(salt.BitLength - keyId.BitLength).ConcatenateBits(keyId); var x = keyId.XOR(salt); var derivedKey = new BitString(0); for (short i = 0; i < m; i++) { var inBlock = x.ConcatenateBits(BitString.To16BitString(i)); var param = new ModeBlockCipherParameters(BlockCipherDirections.Encrypt, key, inBlock); derivedKey = derivedKey.ConcatenateBits(_aesEcb.ProcessPayload(param).Result); } return(derivedKey.GetMostSignificantBits(length)); }
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); }
protected override DrbgResult GenerateAlgorithm(int requestedNumberOfBits, BitString additionalInput) { // 1 if (ReseedCounter > Attributes.MaxNumberOfRequestsBetweenReseeds) { return(new DrbgResult(DrbgStatus.ReseedRequired)); } // 2 if (additionalInput.BitLength != 0) { Update(additionalInput); } // 3 var temp = new BitString(0); // 4 while (temp.BitLength < requestedNumberOfBits) { // 4.1 V = _hmac.Generate(Key, V).Mac; // 4.2 temp = temp.ConcatenateBits(V); } // 5 var returnedBits = temp.GetMostSignificantBits(requestedNumberOfBits); // 6 Update(additionalInput); // 7 ReseedCounter++; // 8 return(new DrbgResult(returnedBits)); }
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); }
// [TestCase(5)] // [TestCase(6)] // [TestCase(7)] public void TestMultipleBitLengthsOfZz(int bitsToDrop) { var zz = new BitString("51020F0B4423F066FFA2B9CA5FA536603F307A52048D7FBE4FA2D0A8F5B6ACF116BE68A28F6D21C37A4A76F082A5CE0D240FB84D6E3291C9B49E6865E76AB166934C701DB25A7FF77DE8849657244CB818B813B72D404D86DC1B0CFF64AFABFEE0CE24DF6DD6C537B6E58DBBC96DD4B18DDD0583699234B82BDDF4778236DD0B944E042BE5DA951E4B7D4962086964D0929F3641AB403CE4FA0AB9F2E500A5004786153E3E7740C41EA0C396773EC2D5D0E98837372491B97C42A336AEA3CF1F13C090CB3F45BA1AC67D763D09B9279D4158A6B41FB8C0E8515473F882174184EDDD5FAECC043E779DA7F0080CE31DE03B255DE038ACEC636F6CDF7DCD47B2C6757310179952B29F48DF510C2C204520C2313034DDB7080DE4F9018EA37756FEA41C285213E0216B5A3BA730AAC15C60EB72E5143656E2ADD533F7CACE1CCAE0100BDD789130A3B755669BC064DD31ECB3CFAB6E5766FA7194C982B79776D1F5FC1C1DECBE102096E14C7B30C8876757EB9F419002C6FC2DE88B98B1C784F3C0976447DC352D8BF56FBE255394E2FD3D7B5A4C9B4770"); zz = zz.GetMostSignificantBits(zz.BitLength - bitsToDrop); var otherInfo = new BitString("82852BF64C6CF56399CC0E5F7ADAE2DF286B51E0D1A274BE949AF3D72A29CBB21F8AC17574BB12550804F4A8AA498082"); var hashFunction = new HashFunction(ModeValues.SHA1, DigestSizes.d160); var sha = _factory.GetShaInstance(hashFunction); var subject = new AnsiX942Concat(sha); var param = new ConcatAns942Parameters { Zz = zz, KeyLen = 384, OtherInfo = otherInfo }; var result = subject.DeriveKey(param); Assert.True(result.Success); Assert.AreEqual(new BitString("DD8469A101758AA949516B0AE4B8F6B56438A0A119575D3265163C6BBBEA2CB58629F387A1AA163D5AE164C5206E1DB5").ToHex(), result.DerivedKey.ToHex()); }