Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 测试来自C的AES-NI指令#_C#_.net_Aes - Fatal编程技术网

C# 测试来自C的AES-NI指令#

C# 测试来自C的AES-NI指令#,c#,.net,aes,C#,.net,Aes,我想知道是否有办法从C#NET测试主机系统的CPU中是否存在AES-NI 让我先说一下,这个问题不是问如何使用.NET中的AES-NI。事实证明,如果AES-NI可用,只需使用AESCryptServiceProvider即可。该结果基于我所做的独立基准测试,将AESCryptServiceProvider的性能与TrueCrypt中提供的基准测试进行比较,TrueCrypt确实支持AES-NI。结果惊人地相似,在两台机器上有和没有AES-NI 我希望能够测试它的原因是能够向用户指示他们的计算机

我想知道是否有办法从C#NET测试主机系统的CPU中是否存在AES-NI

让我先说一下,这个问题不是问如何使用.NET中的AES-NI。事实证明,如果AES-NI可用,只需使用
AESCryptServiceProvider
即可。该结果基于我所做的独立基准测试,将
AESCryptServiceProvider
的性能与TrueCrypt中提供的基准测试进行比较,TrueCrypt确实支持AES-NI。结果惊人地相似,在两台机器上有和没有AES-NI

我希望能够测试它的原因是能够向用户指示他们的计算机支持AES-NI。这将是相关的,因为它将减少涉及“但我的朋友也有一个核心i5,但他的速度快得多!”等问题的支持事件。如果程序的用户界面可以向用户表明他们的系统支持或不支持AES-NI,也可以指出这一点“由于此系统不支持AES-NI,因此性能较慢是正常现象。”

(我们可以感谢英特尔对不同处理器步进的所有混淆!:-)


有没有一种方法可以检测到这些信息,也许是通过WMI?

似乎也有类似的问题:答案很好

但是这个答案需要一些调整来适应你的需要

首先,据我所知,AES-NI只能出现在64位处理器上,对吗?然后您可以忽略上面答案中的所有32位代码

其次,您需要ECX寄存器或其第25位,因此必须稍微更改代码:

private static bool IsAESNIPresent()
{
    byte[] sn = new byte[16]; // !!! Here were 8 bytes

    if (!ExecuteCode(ref sn))
        return false;

    var ecx = BitConverter.ToUInt32(sn, 8);
    return (ecx & (1 << 25)) != 0;
}

就我所见,这就是所有的变化。

上面Mark给出的答案非常好,对我来说效果很好,但是我确实注意到,如果应用程序在32位模式下运行,那么ecx寄存器在x86代码中没有被拉入,因此没有检测到AES-NI

我添加了一行,更改了另一行,基本上将对x64代码所做的更改标记应用到x86代码。这也允许您从32位模式查看AES-NI位。不确定它是否会帮助某人,但我想我会发布它

编辑:当我做一些测试时,我注意到x64代码返回的寄存器不正确。EDX在偏移量0x4、0x8和0xC处返回,另外ECX和EDX寄存器在x86代码的不同偏移量处,因此您需要更频繁地检查IntPtr.Size,以便在两种环境中都能正常工作我将ECX寄存器放在0x4,EDX放在0x8,这样就可以正确排列数据

如果有人要求,我可以张贴整个班级,这是一个工作的例子,我从这篇文章和其他人学到的东西

public static bool ExecuteCode(ref byte[] result) {
    byte[] code_x86 = new byte[] {
        0x55,                      /* push ebp */
        0x89, 0xE5,                /* mov  ebp, esp */
        0x57,                      /* push edi */
        0x8b, 0x7D, 0x10,          /* mov  edi, [ebp+0x10] */
        0x6A, 0x01,                /* push 0x1 */
        0x58,                      /* pop  eax */
        0x53,                      /* push ebx */
        0x0F, 0xA2,                /* cpuid    */
        0x89, 0x07,                /* mov  [edi], eax */
        0x89, 0x4F, 0x04,          /* mov  [edi+0x4], ecx Changed */
        0x89, 0x57, 0x08,          /* mov  [edi+0x8], edx Changed */
        0x5B,                      /* pop  ebx */
        0x5F,                      /* pop  edi */
        0x89, 0xEC,                /* mov  esp, ebp */
        0x5D,                      /* pop  ebp */
        0xC2, 0x10, 0x00,          /* ret  0x10 */
    };
    byte[] code_x64 = new byte[] {
        0x53,                                     /* push rbx */
        0x48, 0xC7, 0xC0, 0x01, 0x00, 0x00, 0x00, /* mov rax, 0x1 */
        0x0f, 0xA2,                               /* cpuid */
        0x41, 0x89, 0x00,                         /* mov [r8], eax */
        0x41, 0x89, 0x48, 0x04,                   /* mov [r8+0x4], ecx Changed */
        0x41, 0x89, 0x50, 0x08,                   /* mov [r8+0x8], edx Changed*/
        0x5B,                                     /* pop rbx */
        0xC3,                                     /* ret */
    };

    int num;
    byte[] code = (IntPtr.Size == 4) ? code_x86 : code_x64;
    IntPtr ptr = new IntPtr(code.Length);

    if (!VirtualProtect(code, ptr, PAGE_EXECUTE_READWRITE, out num))
        Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());

    ptr = new IntPtr(result.Length);

    return (ExecuteNativeCode(code, IntPtr.Zero, 0, result, ptr) != IntPtr.Zero);

不知道答案,但我首先要看的是一些操作系统WMI调用。与论坛网站不同,我们不使用“谢谢”或“感谢任何帮助”或签名。请参阅。从外观上看,您需要调用EAX设置为1的汇编指令,这将在EDX和ECX中为处理器功能输出一些位标志。您关心ECX中的位25被设置为1,这意味着它支持AES-NI。唯一的问题是我无法找到通过托管代码或WMI从CPUID获取ECX值的方法。我最近得到的是WMI调用<代码>代码> WIN32处理器> /COD>属性,它是CPUID调用之后Eax和EDX寄存器的位掩码,但它不包括您关心的ECX。我如何在C++(GCC)上在Windows上做同样的操作?@ CANADANANYORD共和党,GCC支持CPUID:
public static bool ExecuteCode(ref byte[] result) {
    byte[] code_x86 = new byte[] {
        0x55,                      /* push ebp */
        0x89, 0xE5,                /* mov  ebp, esp */
        0x57,                      /* push edi */
        0x8b, 0x7D, 0x10,          /* mov  edi, [ebp+0x10] */
        0x6A, 0x01,                /* push 0x1 */
        0x58,                      /* pop  eax */
        0x53,                      /* push ebx */
        0x0F, 0xA2,                /* cpuid    */
        0x89, 0x07,                /* mov  [edi], eax */
        0x89, 0x4F, 0x04,          /* mov  [edi+0x4], ecx Changed */
        0x89, 0x57, 0x08,          /* mov  [edi+0x8], edx Changed */
        0x5B,                      /* pop  ebx */
        0x5F,                      /* pop  edi */
        0x89, 0xEC,                /* mov  esp, ebp */
        0x5D,                      /* pop  ebp */
        0xC2, 0x10, 0x00,          /* ret  0x10 */
    };
    byte[] code_x64 = new byte[] {
        0x53,                                     /* push rbx */
        0x48, 0xC7, 0xC0, 0x01, 0x00, 0x00, 0x00, /* mov rax, 0x1 */
        0x0f, 0xA2,                               /* cpuid */
        0x41, 0x89, 0x00,                         /* mov [r8], eax */
        0x41, 0x89, 0x48, 0x04,                   /* mov [r8+0x4], ecx Changed */
        0x41, 0x89, 0x50, 0x08,                   /* mov [r8+0x8], edx Changed*/
        0x5B,                                     /* pop rbx */
        0xC3,                                     /* ret */
    };

    int num;
    byte[] code = (IntPtr.Size == 4) ? code_x86 : code_x64;
    IntPtr ptr = new IntPtr(code.Length);

    if (!VirtualProtect(code, ptr, PAGE_EXECUTE_READWRITE, out num))
        Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());

    ptr = new IntPtr(result.Length);

    return (ExecuteNativeCode(code, IntPtr.Zero, 0, result, ptr) != IntPtr.Zero);