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 override SymmetricCipherResult Encrypt(BitString key, BitString plainText, bool wrapWithInverseCipher) { // 1. Let ICV2 = 0xA65959A6 // 2. Let padlen = 8 * ceil(len(P)/64) - len(P)/8 var padLen = 8 * (int)System.Math.Ceiling(plainText.BitLength / 64.0) - (plainText.BitLength / 8); // 3. Let PAD = 0^8*padlen var pad = BitString.Zeroes(8 * padLen); // 4. Let S = ICV2 || [len(P)/8] under 2^32 || P || PAD var S = new BitString(0); S = S.ConcatenateBits(Icv2); S = S.ConcatenateBits(BitString.To32BitString(plainText.BitLength / 8)); S = S.ConcatenateBits(plainText); S = S.ConcatenateBits(pad); if (plainText.BitLength <= 64) { var aesResult = Cipher.ProcessPayload(new ModeBlockCipherParameters(BlockCipherDirections.Encrypt, key, S, wrapWithInverseCipher)); return(aesResult.Success ? new SymmetricCipherResult(aesResult.Result) : new SymmetricCipherResult(aesResult.ErrorMessage)); } else { var c = Wrap(key, S, wrapWithInverseCipher); return(new SymmetricCipherResult(c)); } }
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)); }
// 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); }
private BitString ConcatenatePieceOntoOtherInfo(string workingPiece) { BitString oi = new BitString(0); if (workingPiece.Equals("uPartyInfo", StringComparison.OrdinalIgnoreCase)) { if (_thisPartyKeyAgreementRole == KeyAgreementRole.InitiatorPartyU) { oi = oi.ConcatenateBits(BitString.GetAtLeastZeroLengthBitString(_thisPartyOtherInfo.PartyId)); oi = oi.ConcatenateBits(BitString.GetAtLeastZeroLengthBitString(_thisPartyOtherInfo.DkmNonce)); } else { oi = oi.ConcatenateBits(BitString.GetAtLeastZeroLengthBitString(_otherPartyOtherInfo.PartyId)); oi = oi.ConcatenateBits(BitString.GetAtLeastZeroLengthBitString(_otherPartyOtherInfo.DkmNonce)); } return(oi); } if (workingPiece.Equals("vPartyInfo", StringComparison.OrdinalIgnoreCase)) { if (_thisPartyKeyAgreementRole == KeyAgreementRole.ResponderPartyV) { oi = oi.ConcatenateBits(BitString.GetAtLeastZeroLengthBitString(_thisPartyOtherInfo.PartyId)); oi = oi.ConcatenateBits(BitString.GetAtLeastZeroLengthBitString(_thisPartyOtherInfo.DkmNonce)); } else { oi = oi.ConcatenateBits(BitString.GetAtLeastZeroLengthBitString(_otherPartyOtherInfo.PartyId)); oi = oi.ConcatenateBits(BitString.GetAtLeastZeroLengthBitString(_otherPartyOtherInfo.DkmNonce)); } return(oi); } if (workingPiece.Equals("counter", StringComparison.OrdinalIgnoreCase)) { oi = oi.ConcatenateBits(new BitString(32).BitStringAddition(BitString.One())); return(oi); } if (workingPiece.StartsWith("literal[", StringComparison.OrdinalIgnoreCase)) { // remove the "literal[]" to get just the hex value workingPiece = workingPiece.Replace("literal[", "").Replace("]", ""); oi = oi.ConcatenateBits(new BitString(workingPiece)); return(oi); } throw new ArgumentException(nameof(workingPiece)); }
// 30 1d // 30 13 // 06 0b 2a 86 48 86 f7 0d 01 09 10 03 06 ; 3DES wrap OID // 04 04 // 00 00 00 01 ; Counter // ; a0 omitted (not present), PartyAInfo (Optional) // a2 06 ; a2 is flag for supplemental info (keyLength) // 04 04 // 00 00 00 c0 ; KeyLen (192 bits in this example) // 30 61 // 30 13 // 06 0b 2a 86 48 86 f7 0d 01 09 10 03 06 // 04 04 // 00 00 00 01 // a0 42 // 04 40 ff e9 be b1 2d 30 aa a6 a6 2d 7f 6e eb 1c f3 bb 43 d4 44 53 4d 61 b4 4f f5 d6 67 5b f5 11 dd b5 d8 4a 55 24 64 fa 40 f8 3e cd 07 29 9c 18 04 b9 37 6d 4a c0 90 12 aa 0b 7a 51 a4 ea 96 ab ae f6 // a2 06 // 04 04 // 00 00 00 c0 // 30 1D // 30 13 // 06 0B 2A 86 48 86 F7 0D 01 09 10 03 06 // 04 04 // 00 00 00 01 // A2 06 // 04 04 // 00 00 01 00 private BitString DerEncode(DerAns942Parameters derParams, BitString counter) { // Octet type || 4 bytes || value var counterOctet = AnsDerEncodingHelper.EncodeOctet(counter); // Concatenate OID and Counter as a sequence var algorithmIdentifier = AnsDerEncodingHelper.EncodeSequence(derParams.Oid.ConcatenateBits(counterOctet)); // All optional information // a0-a3 || len || value var wrappedOtherInfo = new BitString(0); if (derParams.PartyUInfo.BitLength > 0) { wrappedOtherInfo = AnsDerEncodingHelper.EncodePartyUInfo(derParams.PartyUInfo); } if (derParams.PartyVInfo.BitLength > 0) { wrappedOtherInfo = BitString.ConcatenateBits(wrappedOtherInfo, AnsDerEncodingHelper.EncodePartyVInfo(derParams.PartyVInfo)); } if (derParams.SuppPubInfo.BitLength > 0) { wrappedOtherInfo = BitString.ConcatenateBits(wrappedOtherInfo, AnsDerEncodingHelper.EncodeSuppPubInfo(derParams.SuppPubInfo)); } if (derParams.SuppPrivInfo.BitLength > 0) { wrappedOtherInfo = BitString.ConcatenateBits(wrappedOtherInfo, AnsDerEncodingHelper.EncodeSuppPrivInfo(derParams.SuppPrivInfo)); } // OuterWrapper (Sequence) || length || content var fullEncoding = AnsDerEncodingHelper.EncodeSequence(algorithmIdentifier.ConcatenateBits(wrappedOtherInfo)); return(fullEncoding); }
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))); }
public override PaddingResult Pad(int nlen, BitString message) { // 1. Message Hashing var hashedMessage = Sha.HashMessage(message).Digest; // 2. Hash Encapsulation var trailer = GetTrailer(); // Header is always 4, trailer is always 16 var paddingLen = nlen - Header.BitLength - Sha.HashFunction.OutputLen - trailer.BitLength; var padding = GetPadding(paddingLen); // ERROR: Split the padding into two chunks and put the hashed message in the middle var firstChunkPadding = padding.GetMostSignificantBits(paddingLen - 8); var secondChunkPadding = padding.GetLeastSignificantBits(8); var IR = Header.GetDeepCopy(); IR = BitString.ConcatenateBits(IR, firstChunkPadding); IR = BitString.ConcatenateBits(IR, hashedMessage); IR = BitString.ConcatenateBits(IR, secondChunkPadding); IR = BitString.ConcatenateBits(IR, trailer); if (IR.BitLength != nlen) { return(new PaddingResult("Improper length for IR")); } return(new PaddingResult(IR)); }
// Override with good or bad padding methods public virtual PaddingResult Pad(int nlen, BitString message) { // 1. Message Hashing var hashedMessage = Sha.HashMessage(message).Digest; // 2. Hash Encapsulation var trailer = GetTrailer(); // Header is always 4, trailer is always 16 var paddingLen = nlen - Header.BitLength - Sha.HashFunction.OutputLen - trailer.BitLength; var padding = GetPadding(paddingLen); var IR = Header.GetDeepCopy(); IR = BitString.ConcatenateBits(IR, padding); IR = BitString.ConcatenateBits(IR, hashedMessage); IR = BitString.ConcatenateBits(IR, trailer); if (IR.BitLength != nlen) { return(new PaddingResult("Improper length for IR")); } return(new PaddingResult(IR)); }
private DrbgStatus InstantiateNoDf(BitString entropyInput, BitString personalizationString) { // 1. temp = len(personalization_string) int temp = personalizationString.BitLength; // 2. If (temp < seedlen) then personalization_string = // personalization_string || 0^(seedlen - temp) if (temp < CounterAttributes.SeedLength) { personalizationString = personalizationString .ConcatenateBits(new BitString(CounterAttributes.SeedLength - temp)); // Add zeroes to bitstring to make it equal the SeedLength } // 3. seed_material = entropy_input xor personalization_string BitString seedMaterial = entropyInput.XOR(personalizationString); // 4. Key = 0^keylen Key = new BitString(CounterAttributes.KeyLength); // 5. V = 0^outlen V = new BitString(CounterAttributes.OutputLength); // 6. (Key, V) = Update(seed_material, Key, V) // NOTE: update uses member variables m_Key and m_V // for input and output of Key and V Update(seedMaterial); ReseedCounter = 1; return(DrbgStatus.Success); }
/// <summary> /// Call this method to format correctly for KMAC /// </summary> /// <param name="message">BitString representation of message</param> /// <param name="capacity">Capacity</param> /// <param name="customizationString">Character string for customization</param> /// <returns>Formatted message before calling Keccak</returns> public static BitString FormatMessage(BitString message, BitString key, int capacity, int macLength, bool xof) { var macLengthBitString = new BitString(new System.Numerics.BigInteger(macLength)); BitString newMessage; if (capacity == 256) { newMessage = Sha3DerivedHelpers.Bytepad(Sha3DerivedHelpers.EncodeString(key), new BitString("A8")); // "A8" is 164 (the rate) } else // capacity == 512 { newMessage = Sha3DerivedHelpers.Bytepad(Sha3DerivedHelpers.EncodeString(key), new BitString("88")); // "88" is 136 (the rate) } if (xof) { var concatenatedMessageEncode = Sha3DerivedHelpers.SafeConcatenation(message, Sha3DerivedHelpers.RightEncode(BitString.Zeroes(8))); newMessage = BitString.ConcatenateBits(newMessage, concatenatedMessageEncode); } else { var concatenatedMessageEncode = Sha3DerivedHelpers.SafeConcatenation(message, Sha3DerivedHelpers.RightEncode(macLengthBitString)); newMessage = BitString.ConcatenateBits(newMessage, concatenatedMessageEncode); } return(newMessage); }
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 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 override PaddingResult Pad(int nlen, BitString message) { // 1. Message Hashing var hashedMessage = Sha.HashMessage(message).Digest; // 2. Hash Encapsulation var trailer = new BitString("66CC"); // ERROR: The first byte of the trailer is unexpected // Header is always 4, trailer is always 16 var paddingLen = nlen - Header.BitLength - Sha.HashFunction.OutputLen - trailer.BitLength; var padding = GetPadding(paddingLen); var IR = Header.GetDeepCopy(); IR = BitString.ConcatenateBits(IR, padding); IR = BitString.ConcatenateBits(IR, hashedMessage); IR = BitString.ConcatenateBits(IR, trailer); // ERROR: Change the trailer to something else if (IR.BitLength != nlen) { return(new PaddingResult("Improper length for IR")); } return(new PaddingResult(IR)); }
protected override BitString ComputeSharedSecret(OtherPartySharedInformation <EccDomainParameters, EccKeyPair> otherPartyInformation) { // static secret composed of both parties static key parts var staticSecret = _diffieHellman.GenerateSharedSecretZ( DomainParameters, StaticKeyPair, otherPartyInformation.StaticPublicKey ).SharedSecretZ; // differing ephemeralSecret logic depending on key agreement role BitString ephemeralSecret; if (SchemeParameters.KeyAgreementRole == KeyAgreementRole.InitiatorPartyU) { ephemeralSecret = _diffieHellman.GenerateSharedSecretZ( DomainParameters, EphemeralKeyPair, otherPartyInformation.StaticPublicKey ).SharedSecretZ; } else { ephemeralSecret = _diffieHellman.GenerateSharedSecretZ( DomainParameters, StaticKeyPair, otherPartyInformation.EphemeralPublicKey ).SharedSecretZ; } // Shared secret is composed (Z_e || Z_s) return(BitString.ConcatenateBits(ephemeralSecret, staticSecret)); }
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))); }
public TlsKdfResult DeriveKey(BitString preMasterSecret, BitString clientHelloRandom, BitString serverHelloRandom, BitString clientRandom, BitString serverRandom, int keyBlockLength) { var masterSecret = Prf(preMasterSecret, MasterSecretLabel(), clientHelloRandom.ConcatenateBits(serverHelloRandom), 384); var keyBlock = Prf(masterSecret, "key expansion", serverRandom.ConcatenateBits(clientRandom), keyBlockLength); return(new TlsKdfResult(masterSecret, keyBlock)); }
private void Update(BitString providedData) { // 1 var dataToHmac = V.ConcatenateBits(new BitString("00")).ConcatenateBits(providedData); Key = _hmac.Generate(Key, dataToHmac).Mac; // 2 V = _hmac.Generate(Key, V).Mac; // 3 if (providedData.BitLength == 0) { return; } // 4 dataToHmac = V.ConcatenateBits(new BitString("01")).ConcatenateBits(providedData); Key = _hmac.Generate(Key, dataToHmac).Mac; // 5 V = _hmac.Generate(Key, V).Mac; // 6 return; }
protected override BitString GetEphemeralDataFromKeyContribution(ISecretKeyingMaterial secretKeyingMaterial) { if (secretKeyingMaterial.EphemeralKeyPair != null) { var domainParam = (EccDomainParameters)secretKeyingMaterial.DomainParameters; var exactLength = CurveAttributesHelper.GetCurveAttribute(domainParam.CurveE.CurveName).DegreeOfPolynomial;; var ephemKey = (EccKeyPair)secretKeyingMaterial.EphemeralKeyPair; if (ephemKey.PublicQ.X != 0) { return(BitString.ConcatenateBits( SharedSecretZHelper.FormatEccSharedSecretZ(ephemKey.PublicQ.X, exactLength), SharedSecretZHelper.FormatEccSharedSecretZ(ephemKey.PublicQ.Y, exactLength) )); } } if (secretKeyingMaterial.EphemeralNonce != null && secretKeyingMaterial.EphemeralNonce?.BitLength != 0) { return(secretKeyingMaterial.EphemeralNonce); } return(secretKeyingMaterial.DkmNonce); }
public byte[] HandleFinalFullPayloadBlockDecryption(BitString payload, IBlockCipherEngine engine, int numberOfBlocks, int originalPayloadBitLength) { // Decrypt the last full payload block (when there is more than one block) if (numberOfBlocks > 1) { var originalPayloadPaddedToBlockSize = payload.PadToModulus(engine.BlockSizeBits).ToBytes(); // Decrypt the last full payload block (in this case the second to last block) var secondToLastBlock = new byte[engine.BlockSizeBytes]; var secondToLastBlockStartIndex = (numberOfBlocks - 2) * engine.BlockSizeBytes; Array.Copy(originalPayloadPaddedToBlockSize, secondToLastBlockStartIndex, secondToLastBlock, 0, engine.BlockSizeBytes); var decryptedSecondToLastBlockBuffer = new byte[engine.BlockSizeBytes]; engine.ProcessSingleBlock(secondToLastBlock, decryptedSecondToLastBlockBuffer, 0); var decryptedBlock = new BitString(decryptedSecondToLastBlockBuffer); // Pad the payload to the nearest multiple of the block size using the last B−M bits of block cipher decryption of the second-to-last ciphertext block. var amountToPad = (engine.BlockSizeBits - payload.BitLength % engine.BlockSizeBits); if (amountToPad > 0) { payload = payload.ConcatenateBits(BitString.Substring(decryptedBlock, 0, amountToPad)); } var payloadBytes = payload.ToBytes(); TransformText(payloadBytes, engine, numberOfBlocks, originalPayloadBitLength); payload = new BitString(payloadBytes); return(payload.ToBytes()); } return(payload.ToBytes()); }
protected override BitString ComputeSharedSecret(ISecretKeyingMaterial otherPartyKeyingMaterial) { var domainParameters = (EccDomainParameters)ThisPartyKeyingMaterial.DomainParameters; // static secret composed of both parties static key parts var staticSecret = _diffieHellman.GenerateSharedSecretZ( domainParameters, (EccKeyPair)ThisPartyKeyingMaterial.StaticKeyPair, (EccKeyPair)otherPartyKeyingMaterial.StaticKeyPair ).SharedSecretZ; // differing ephemeralSecret logic depending on key agreement role BitString ephemeralSecret; if (SchemeParameters.KeyAgreementRole == KeyAgreementRole.InitiatorPartyU) { ephemeralSecret = _diffieHellman.GenerateSharedSecretZ( domainParameters, (EccKeyPair)ThisPartyKeyingMaterial.EphemeralKeyPair, (EccKeyPair)otherPartyKeyingMaterial.StaticKeyPair ).SharedSecretZ; } else { ephemeralSecret = _diffieHellman.GenerateSharedSecretZ( domainParameters, (EccKeyPair)ThisPartyKeyingMaterial.StaticKeyPair, (EccKeyPair)otherPartyKeyingMaterial.EphemeralKeyPair ).SharedSecretZ; } // Shared secret is composed (Z_e || Z_s) return(BitString.ConcatenateBits(ephemeralSecret, staticSecret)); }
// returns null if keyPair is exhausted public async Task <HssSignatureResult> GenerateHssSignatureAsync(BitString msg, HssKeyPair keyPair, int advanced = 0) { // 1. If the message-signing key prv[L - 1] is exhausted, regenerate that key pair, together with any // parent key pairs that might be necessary. If the root key pair is exhausted, then the HSS key pair is // exhausted and MUST NOT generate any more signatures. keyPair = await UpdateKeyPairAsync(keyPair, advanced); if (keyPair.Expired) { return(new HssSignatureResult("Key expired.")); } // 2. Sign the message. var sig = _lms[_lms.Length - 1].GenerateLmsSignature(msg, keyPair.PrivateKey.PrivateKeys[_lms.Length - 1]); // 3. Create the list of signed public keys. var signedPubKey = new BitString(""); for (int i = 0; i < _lms.Length - 1; i++) { signedPubKey = signedPubKey.ConcatenateBits(keyPair.PrivateKey.Signatures[i]) .ConcatenateBits(keyPair.PrivateKey.PublicKeys[i + 1]); } // 4. Return u32str(L-1) || signed_pub_key[0] || ... || signed_pub_key[L - 2] || sig[L - 1] return(new HssSignatureResult(new BitString(_lms.Length - 1, 32).ConcatenateBits(signedPubKey).ConcatenateBits(sig))); }
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); }
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); }
private BitString PseudoRandomFunction(BitString k, BitString h, char letter, BitString sessionId, int L) { var N = L.CeilingDivide(_hash.HashFunction.OutputLen); var charArray = new[] { letter }; var message = k.ConcatenateBits(h).ConcatenateBits(new BitString(Encoding.ASCII.GetBytes(charArray))).ConcatenateBits(sessionId); var kOut = _hash.HashMessage(message).Digest; for (var i = 0; i < N; i++) { var hashIn = k.ConcatenateBits(h).ConcatenateBits(kOut); var kI = _hash.HashMessage(hashIn).Digest; kOut = kOut.ConcatenateBits(kI); } return(kOut.GetMostSignificantBits(L)); }
public BigInteger GetFullSeed() { var seedBS = new BitString(Seed).PadToModulusMsb(32); var pSeedBS = new BitString(PSeed).PadToModulusMsb(32); var qSeedBS = new BitString(QSeed).PadToModulusMsb(32); return(BitString.ConcatenateBits(seedBS, BitString.ConcatenateBits(pSeedBS, qSeedBS)).ToPositiveBigInteger()); }
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 EdSignatureResult Sign(EdDomainParameters domainParameters, EdKeyPair keyPair, BitString message, BitString context, bool preHash = false) { Sha = domainParameters.Hash; // If preHash version, then the message becomes the hash of the message if (preHash) { message = Sha.HashMessage(message, 512).Digest; } // 1. Hash the private key var hashResult = HashPrivate(domainParameters, keyPair.PrivateD); // 2. Compute r // Determine dom. Empty if ed25519. Different for preHash function BitString dom; if (preHash) { dom = domainParameters.CurveE.CurveName == Curve.Ed448 ? Dom4(1, context) : Dom2(1, context); } else { dom = domainParameters.CurveE.CurveName == Curve.Ed448 ? Dom4(0, context) : new BitString(""); } // Hash (dom4 || Prefix || message) var rBits = Sha.HashMessage(BitString.ConcatenateBits(dom, BitString.ConcatenateBits(hashResult.HDigest2, message)), 912).Digest; // Convert rBits to little endian and mod order n var r = BitString.ReverseByteOrder(rBits).ToPositiveBigInteger() % domainParameters.CurveE.OrderN; // 3. Compute [r]G. R is the encoding of [r]G var rG = domainParameters.CurveE.Multiply(domainParameters.CurveE.BasePointG, r); // Encode the point rG into a b-bit bitstring var R = domainParameters.CurveE.Encode(rG); // 4. Define S // Hash (dom4 || R || Q || M). Need to use dom4 if ed448 var hashData = BitString.ConcatenateBits(keyPair.PublicQ, message); hashData = BitString.ConcatenateBits(dom, BitString.ConcatenateBits(R, hashData)); var hash = Sha.HashMessage(hashData, 912).Digest; // Convert hash to int from little endian and mod order n var hashInt = BitString.ReverseByteOrder(hash).ToPositiveBigInteger() % domainParameters.CurveE.OrderN; // Determine s as done in key generation var s = NumberTheory.Pow2(domainParameters.CurveE.VariableN) + hashResult.Buffer.ToPositiveBigInteger(); // Calculate S as an BigInteger var Sint = (r + (hashInt * s)).PosMod(domainParameters.CurveE.OrderN); // Encode S in little endian var S = BitString.ReverseByteOrder(new BitString(Sint, domainParameters.CurveE.VariableB)); // 5. Form the signature by concatenating R and S return new EdSignatureResult(new EdSignature(R, S)); }
public override SymmetricCipherResult Encrypt(BitString key, BitString plainText, bool wrapWithInverseCipher) { // 1. Let ICV1 = 0xA6A6A6A6A6A6A6A6 // 2. Let S = ICV1 || P // 3. Return C = W(S) BitString c = Wrap(key, Icv1.ConcatenateBits(plainText), wrapWithInverseCipher); return(new SymmetricCipherResult(c)); }