JitterEx.cs

using System;
using System.Diagnostics;
using System.Linq;
using System.Management;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Threading;
[Serializable]
public class JitterEx
{
    private const    int                      DesaturationLoopLimit = 500;
    private const    int                      UpperCpuLoadLimit     = 90;
    private const    int                      LowerCpuLoadLimit     = 10;
    private static   bool                     _scaleSet;
    private readonly int                      _bufferSize;
    private readonly object                   _lock = new object();
    private readonly RNGCryptoServiceProvider _prng;
    private          byte[]                   _rngCache;
    private          int                      _tscLoopLimitCpu  = 20;
    private          int                      _tscSampleSizeRam = 10;
    public JitterEx(int buffersize)
    {
        if (buffersize < 256)
            throw new ArgumentException("Buffer Size cannot be less than 256 bytes.");
        _bufferSize = buffersize;
        _rngCache   = new byte[_bufferSize];
        _prng       = new RNGCryptoServiceProvider();
        SetScale();
    }
    private float GetCpuSpeed()
    {
        void Loop()
        {
            var i = 0;
            while (true)
                i = i + 1 - 1;
        }
        var cpuCounter = new PerformanceCounter("Processor Information", "% Processor Performance", "_Total");
        var cpuValue   = cpuCounter.NextValue();
        var loop       = new Thread(() => Loop()) {Priority = ThreadPriority.Highest};
        var Speed      = 0f;
        lock (_lock)
        {
            loop.Start();
            Thread.Sleep(60);
            cpuValue = cpuCounter.NextValue();
            loop.Abort();
        }
        foreach (ManagementObject obj in new ManagementObjectSearcher("SELECT *, Name FROM Win32_Processor").Get())
            Speed = Convert.ToSingle(obj["MaxClockSpeed"]) / 1000 * cpuValue / 100;
        return Speed;
    }
    /// <summary>
    ///     This is a fairly arbitrary value which is based on the CPU speed
    /// </summary>
    private void SetScale()
    {
        if (_scaleSet)
            return;
        _scaleSet = true;
        const float baseFreq = 4.277f;
        var         thisFreq = GetCpuSpeed();
        var         rat      = baseFreq / thisFreq;
        _tscLoopLimitCpu  = (int) Math.Ceiling(_tscLoopLimitCpu  * rat);
        _tscSampleSizeRam = (int) Math.Ceiling(_tscSampleSizeRam * rat);
    }
    private void LoadBlock()
    {
        var DesaturationLoops = 0;
        var dump              = CpuTotalPc.CPULoad;
        do
        {
            Thread.Sleep(0);
            DesaturationLoops++;
        } while (DesaturationLoops < DesaturationLoopLimit && ((int) CpuTotalPc.CPULoad > UpperCpuLoadLimit || (int) CpuTotalPc.CPULoad < LowerCpuLoadLimit));
    }
    [MethodImpl(MethodImplOptions.NoInlining)]
    private byte[] GetBufferCpu()
    {
        var jitterBuffer = new byte[_bufferSize];
        var loop         = 0;
        while (true)
        {
            var ptr = 0;
            var x   = 0;
            LoadBlock();
            lock (_lock)
            {
                var start = Rdtsc.TimestampP();
                do
                {
                    for (var i = 0; i < _tscLoopLimitCpu; i++)
                        x = x + 1 - 1;
                    var stop = Rdtsc.TimestampP();
                    Buffer.BlockCopy((100000.0 / ((stop - start) * 100000.0)).GetBytes(), 0, jitterBuffer, ptr, 4);
                    start =  stop;
                    ptr   += 4;
                } while (ptr < _bufferSize);
                return jitterBuffer;
            }
        }
        return jitterBuffer;
    }
    [MethodImpl(MethodImplOptions.NoInlining)]
    private unsafe byte[] GetBufferRam()
    {
        LoadBlock();
        var jitterBuffer = new byte[_bufferSize];
        lock (_lock)
        {
            if (_rngCache.Length != _bufferSize)
                _rngCache = new byte[_bufferSize];
            _prng.GetBytes(_rngCache);
            var  ptr = 0;
            byte tempByte;
            var  start = Rdtsc.TimestampP();
            while (true)
            {
                fixed (byte* p1 = _rngCache)
                {
                    var x1 = p1;
                    for (var j = 0; j < _tscSampleSizeRam; ++j, ++x1)
                        tempByte = *x1;
                }
                var stop = Rdtsc.TimestampP();
                Buffer.BlockCopy((100000.0 / ((stop - start) * 100000.0)).GetBytes(), 0, jitterBuffer, ptr, 4);
                start =  stop;
                ptr   += 4;
                if (ptr < _bufferSize)
                {
                    if (_rngCache.Length != _bufferSize)
                        _rngCache = new byte[_bufferSize];
                    _prng.GetBytes(_rngCache);
                }
                else
                {
                    break;
                }
            }
        }
        return jitterBuffer;
    }
    private double Entropy(byte[] ba)
    {
        var map = new int[256];
        foreach (var i in ba)
            map[i]++;
        var lot = Math.Log(2);
        return map.Where(item => item > 0).Select(item => item / (double) ba.Length).Aggregate(0.0, (current, frequency) => current - frequency * (Math.Log(frequency) / lot));
    }
    public byte[] GetBuffer()
    {
        var firstBuffer  = GetBufferCpu();
        var secondBuffer = GetBufferRam();
        var finalBuffer  = new byte[_bufferSize];
        for (var j = 0; j < _bufferSize; ++j)
            finalBuffer[j] = (byte) (firstBuffer[j] ^ secondBuffer[j]);
        return finalBuffer;
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *