public static void Transform(UInt512 state, ulong numRounds, string fileName) { using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) { Transform(state, numRounds, fileStream); } }
private static UInt512 Initialize(UInt512 bState, uint xState0, uint xState1, uint xState2, uint xState3) { var t0 = bState.I0; var t1 = bState.I1; var t2 = bState.I2; var t3 = bState.I3; var t4 = bState.I4; var t5 = bState.I5; var t6 = bState.I6; var t7 = bState.I7; var t8 = bState.I8; var t9 = bState.I9; var tA = bState.IA; var tB = bState.IB; var tC = bState.IC; var tD = bState.ID; var tE = bState.IE; var tF = bState.IF; for (var i = 0UL; i < 10UL; i++) { ChaCha.DoubleRound( ref t0, ref t1, ref t2, ref t3, ref t4, ref t5, ref t6, ref t7, ref t8, ref t9, ref tA, ref tB, ref tC, ref tD, ref tE, ref tF ); } return(new UInt512( ChaCha.SIGMA0, ChaCha.SIGMA1, ChaCha.SIGMA2, ChaCha.SIGMA3, t0, t1, t2, t3, tC, tD, tE, tF, xState0, xState1, xState2, xState3 )); }
public static void Transform(UInt512 state, ulong numRounds, byte[] data) { using (var memoryStream = new MemoryStream(data, true)) { Transform(state, numRounds, memoryStream); } }
public static void Transform(UInt512 state, ulong numRounds, Stream source, Stream destination) { var dataBuffer = new byte[BLOCK_SIZE_IN_BYTES]; var keyStreamBuffer = new byte[BLOCK_SIZE_IN_BYTES]; var keyStreamPosition = Math.CombineIntoUInt64(state.IC, state.ID); var numBytesRead = 0; while (unchecked (BLOCK_SIZE_IN_BYTES - 1) < (numBytesRead = source.Read(dataBuffer, 0, BLOCK_SIZE_IN_BYTES))) { if (source == destination) { destination.Position -= BLOCK_SIZE_IN_BYTES; } BlockRound(state, numRounds, checked (keyStreamPosition++), keyStreamBuffer, 0UL); // get next key stream chunk dataBuffer.VectorXor(keyStreamBuffer, BLOCK_SIZE_IN_BYTES); // xor data chunk with key stream destination.Write(dataBuffer, 0, BLOCK_SIZE_IN_BYTES); // write transformed data chunk to destination stream } if (0 < numBytesRead) { if (source == destination) { destination.Position -= numBytesRead; } BlockRound(state, numRounds, checked (keyStreamPosition++), keyStreamBuffer, 0UL); // get next key stream chunk dataBuffer.VectorXor(keyStreamBuffer, unchecked ((ulong)numBytesRead)); // xor data chunk with key stream destination.Write(dataBuffer, 0, numBytesRead); // write transformed data chunk to destination stream } }
public unsafe XChaCha20(UInt512 state, ulong iv) : base(Initialize(state, checked ((uint)iv.CleaveHigh()), checked ((uint)iv.CleaveLow()), SecureRandom.GetUInt32(), SecureRandom.GetUInt32())) { var nonce = new byte[24]; fixed(byte *d = &nonce[0]) { *(((uint *)d) + 0) = state.IC; *(((uint *)d) + 1) = state.ID; *(((uint *)d) + 2) = state.IE; *(((uint *)d) + 3) = state.IF; *(((ulong *)d) + 2) = base.Nonce; } Nonce = ImmutableArray.Create(nonce); }
public ChaCha20(UInt512 state) { m_state = state; }
/// <summary> /// Fills an array of bytes with the key stream calculated from the specified state, number of rounds, and iv. /// </summary> public unsafe static void BlockRound(UInt512 state, ulong numRounds, ulong iv, byte[] destination, ulong destinationOffset) { if (checked (BLOCK_SIZE_IN_BYTES + destinationOffset) > unchecked ((ulong)destination.LongLength)) { throw new ArgumentOutOfRangeException(paramName: nameof(destinationOffset)); } var counterLow = checked ((uint)iv.CleaveHigh()); var counterHigh = checked ((uint)iv.CleaveLow()); var t0 = state.I0; var t1 = state.I1; var t2 = state.I2; var t3 = state.I3; var t4 = state.I4; var t5 = state.I5; var t6 = state.I6; var t7 = state.I7; var t8 = state.I8; var t9 = state.I9; var tA = state.IA; var tB = state.IB; var tC = counterLow; var tD = counterHigh; var tE = state.IE; var tF = state.IF; for (var i = 0UL; i < (numRounds >> 1); i++) { DoubleRound( ref t0, ref t1, ref t2, ref t3, ref t4, ref t5, ref t6, ref t7, ref t8, ref t9, ref tA, ref tB, ref tC, ref tD, ref tE, ref tF ); } unchecked { t0 += state.I0; t1 += state.I1; t2 += state.I2; t3 += state.I3; t4 += state.I4; t5 += state.I5; t6 += state.I6; t7 += state.I7; t8 += state.I8; t9 += state.I9; tA += state.IA; tB += state.IB; tC += counterLow; tD += counterHigh; tE += state.IE; tF += state.IF; } if (BitConverter.IsLittleEndian) { fixed(byte *d = &destination[destinationOffset]) { *(((uint *)d) + 0) = t0; *(((uint *)d) + 1) = t1; *(((uint *)d) + 2) = t2; *(((uint *)d) + 3) = t3; *(((uint *)d) + 4) = t4; *(((uint *)d) + 5) = t5; *(((uint *)d) + 6) = t6; *(((uint *)d) + 7) = t7; *(((uint *)d) + 8) = t8; *(((uint *)d) + 9) = t9; *(((uint *)d) + 10) = tA; *(((uint *)d) + 11) = tB; *(((uint *)d) + 12) = tC; *(((uint *)d) + 13) = tD; *(((uint *)d) + 14) = tE; *(((uint *)d) + 15) = tF; } } else { fixed(byte *d = &destination[destinationOffset]) { *(((uint *)d) + 0) = t0.ReverseBytes(); *(((uint *)d) + 1) = t1.ReverseBytes(); *(((uint *)d) + 2) = t2.ReverseBytes(); *(((uint *)d) + 3) = t3.ReverseBytes(); *(((uint *)d) + 4) = t4.ReverseBytes(); *(((uint *)d) + 5) = t5.ReverseBytes(); *(((uint *)d) + 6) = t6.ReverseBytes(); *(((uint *)d) + 7) = t7.ReverseBytes(); *(((uint *)d) + 8) = t8.ReverseBytes(); *(((uint *)d) + 9) = t9.ReverseBytes(); *(((uint *)d) + 10) = tA.ReverseBytes(); *(((uint *)d) + 11) = tB.ReverseBytes(); *(((uint *)d) + 12) = tC.ReverseBytes(); *(((uint *)d) + 13) = tD.ReverseBytes(); *(((uint *)d) + 14) = tE.ReverseBytes(); *(((uint *)d) + 15) = tF.ReverseBytes(); } } }
public static void Transform(UInt512 state, ulong numRounds, Stream stream) => Transform(state, numRounds, stream, stream);