将 C# 结构编组到本机 C 库中
Marshaling C# struct into native C library
我目前正在编写一个 NTRUMLS C# wrapper for the NTRUMLS C 库。我正在 运行 遇到一个问题,我认为我没有通过映射到 C 库入口点的外部函数接口正确地编组参数数据。
这是我在ffi.cs
.
中使用的具体外部函数接口
using System;
using System.Runtime.InteropServices;
using NTRUMLS.Params;
namespace NTRUMLS.ffi {
public static class ffi {
[DllImport("ntrumls")]
public static extern int pq_gen_key(ParamSet p, out IntPtr privkey_blob_len, out byte[] privkey_blob, out IntPtr pubkey_blob_len, out byte[] pubkey_blob);
}
}
我传入的特定 ParamSet 结构 param.cs
,我认为这可能是导致问题的具体原因。
using System;
using System.Text;
using System.Runtime.InteropServices;
namespace NTRUMLS.Params {
[SerializableAttribute]
[ComVisibleAttribute(true)]
public enum ParamSetId {
Xxx20140508401,
Xxx20140508439,
Xxx20140508593,
Xxx20140508743,
Xxx20151024401,
Xxx20151024443,
Xxx20151024563,
// Xxx20151024509,
Xxx20151024743,
Xxx20151024907,
}
[StructLayout(LayoutKind.Sequential)]
public struct ParamSet {
ParamSetId id;
IntPtr name;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
byte[] oid;
[MarshalAs(UnmanagedType.U1)]
byte n_bits;
[MarshalAs(UnmanagedType.U1)]
byte q_bits;
[MarshalAs(UnmanagedType.U2)]
ushort n;
[MarshalAs(UnmanagedType.I1)]
sbyte p;
[MarshalAs(UnmanagedType.I8)]
long q;
[MarshalAs(UnmanagedType.I8)]
long b_s;
[MarshalAs(UnmanagedType.I8)]
long b_t;
[MarshalAs(UnmanagedType.I8)]
long norm_bound_s;
[MarshalAs(UnmanagedType.I8)]
long norm_bound_t;
[MarshalAs(UnmanagedType.U1)]
byte d1;
[MarshalAs(UnmanagedType.U1)]
byte d2;
[MarshalAs(UnmanagedType.U1)]
byte d3;
[MarshalAs(UnmanagedType.U2)]
ushort padded_n;
public ushort get_n() {
return n;
}
public sbyte get_p() {
return p;
}
public byte get_d1() {
return d1;
}
public byte get_d2() {
return d2;
}
public byte get_d3() {
return d3;
}
public uint product_form_bytes() {
return (uint)(4 * (d1 + d2 + d3));
}
public uint polynomial_bytes() {
return (uint)(padded_n * 8);
}
public uint privkey_packed_bytes() {
return (uint)(5 + 2 * ((2 * ( d1 + d2 + d3) * n_bits + 7) / 8) + ((n +4) / 5));
}
public uint pubkey_packed_bytes() {
return (uint)(5 + (n * q_bits + 7) / 8 + 64);
}
public ParamSet (ParamSetId ID, IntPtr NAME, byte[] OID, byte N_BITS, byte Q_BITS, ushort N, sbyte P, long Q, long B_S, long B_T, long NORM_BOUND_S, long NORM_BOUND_T, byte D1, byte D2, byte D3, ushort PADDED_N) {
id = ID;
name = NAME;
oid = OID;
n_bits = N_BITS;
q_bits = Q_BITS;
n = N;
p = P;
q = Q;;
b_s = B_S;
b_t = B_T;
norm_bound_s = NORM_BOUND_S;
norm_bound_t = NORM_BOUND_T;
d1 = D1;
d2 = D2;
d3 = D3;
padded_n = PADDED_N;
}
}
public static class ParamSets {
/// <summary>
/// 256 bit security parameter
/// </summary>
public static readonly ParamSet Xxx20140508_743 = new ParamSet(
ParamSetId.Xxx20140508743,
Marshal.StringToHGlobalAuto("Xxx20140508743"),
new byte[] {0xff, 0xff, 0xfc},
10,
20,
743,
3,
1 << 20,
336,
112,
(1 << 19) - 336,
(1 << 19) - 112,
11,
11,
15,
768);
}
}
这是包装器本身 NTRUMLSWrapper.cs
。
using NTRUMLS.ffi;
using NTRUMLS.Params;
using System;
using System.Runtime.InteropServices;
namespace NTRUMLS.Library {
public static class NTRUMLSWrapper {
public static KeyPair generate_keys(ParamSet param) {
int pub_len = 0;
int priv_len = 0;
Console.WriteLine("Param N: " + param.get_n());
Console.WriteLine("Param P: " + param.get_p());
Console.WriteLine("Param D1: " + param.get_d1());
Console.WriteLine("Param D2: " + param.get_d2());
Console.WriteLine("Param D3: " + param.get_d3());
GCHandle pub_len_handle = GCHandle.Alloc(pub_len);
GCHandle priv_len_handle = GCHandle.Alloc(priv_len);
IntPtr privkey_blob_len = (IntPtr)pub_len_handle;
IntPtr pubkey_blob_len = (IntPtr)priv_len_handle;
GCHandle handle = GCHandle.Alloc(param);
IntPtr paramater = (IntPtr)handle;
byte[] pv = new byte[priv_len];
byte[] pb = new byte[pub_len];
// GCHandle pv_handle = GCHandle.Alloc(pv);
// GCHandle pb_handle = GCHandle.Alloc(pb);
var result = ffi.ffi.pq_gen_key(param, out privkey_blob_len, out pv, out pubkey_blob_len, out pb);
Console.WriteLine("Result: " + result + " Private Key BLob Length: " + priv_len + " Public Key Blob Lengh: " + pub_len);
if (result != 0)
Console.WriteLine("We got problems");
byte[] privatekey_blob = new byte[privkey_blob_len.ToInt64()];
byte[] pubkey_blob = new byte[pubkey_blob_len.ToInt64()];
result = ffi.ffi.pq_gen_key(param, out privkey_blob_len, out privatekey_blob, out pubkey_blob_len, out pubkey_blob);
if (result != 0)
Console.WriteLine("We got problems");
Console.WriteLine("Result: " + result.ToString() + " Private Key BLob Length: " + privkey_blob_len + " Public Key Blob Lengh: " + pubkey_blob_len);
// byte[] privkeyBytes = new byte[priv_len.ToInt32()];
// byte[] pubkeyBytes = new byte[pub_len.ToInt32()];
return new KeyPair(new PrivateKey(pubkey_blob), new PublicKey(privatekey_blob));;
}
}
public struct PrivateKey {
byte[] ffi_key;
public PrivateKey (byte[] bytes) {
ffi_key = bytes;
}
public byte[] get_bytes() {
return ffi_key;
}
}
public struct PublicKey {
byte[] ffi_key;
public PublicKey (byte[] bytes) {
ffi_key = bytes;
}
public byte[] get_bytes() {
return ffi_key;
}
}
public struct KeyPair {
PublicKey publicKey;
PrivateKey privateKey;
public KeyPair(PrivateKey privKey, PublicKey pubkey)
{
publicKey = pubkey;
privateKey = privKey;
}
public PublicKey getPublic()
{
return publicKey;
}
public PrivateKey getPrivate()
{
return privateKey;
}
}
}
并且 Program.cs
到 运行 密钥生成测试。
using System;
using NTRUMLS.Library;
using NTRUMLS.Params;
namespace NTRUMLS
{
public class Program
{
public static void Main(string[] args)
{
KeyPair keypair = NTRUMLSWrapper.generate_keys(ParamSets.Xxx20140508_743);
Console.WriteLine("Generated Keys!");
// TODO Sign, than Verify to confirm test
}
}
}
这是我编组到的 C 函数的头函数
在pqntrusign.h
int
pq_gen_key(
PQ_PARAM_SET *params,
size_t *privkey_blob_len,
unsigned char *privkey_blob,
size_t *pubkey_blob_len,
unsigned char *pubkey_blob);
在 params.h
和 params.c
enum _PQ_PARAM_SET_ID {
XXX_20140508_401,
XXX_20140508_439,
XXX_20140508_593,
XXX_20140508_743,
XXX_20151024_401,
XXX_20151024_443,
XXX_20151024_563,
//XXX_20151024_509,
XXX_20151024_743,
XXX_20151024_907,
};
struct _PQ_PARAM_SET {
PQ_PARAM_SET_ID id; /* parameter set id */
const char *name; /* human readable name */
const uint8_t OID[3]; /* OID */
uint8_t N_bits; /* ceil(log2(N)) */
uint8_t q_bits; /* ceil(log2(q)) */
uint16_t N; /* ring degree */
int8_t p; /* message space prime */
int64_t q; /* ring modulus */
int64_t B_s; /* max norm of f*a convolution */
int64_t B_t; /* max norm of g*a convolution */
int64_t norm_bound_s;/* q/2 - B_s */
int64_t norm_bound_t;/* q/2 - B_t */
uint8_t d1; /* Product form +1/-1 counts */
uint8_t d2;
uint8_t d3;
uint16_t padded_N; /* # Polynomial coefficients for Karatsuba */
};
我认为当前的问题是 ParamSet struct
,以及将名称属性与 C 结构 const char*name
指针属性正确匹配。但是,我不完全确定是这样。
我修改了 NTRUMLS C pqntrusign.c
源文件以打印到 log.txt 并记录我传递的变量。这是我在 int pq_gen_key
函数开头添加的片段。
FILE * fp;
fp = fopen ("log.txt", "a+");
fprintf(fp, "Logging made it here variables priv_blob_len_pointer %i pub_blob_len_pointer %i priv_blob_len %i pub_blob_len %i privkey %x pubkey %x \n", privkey_blob_len, pubkey_blob_len, *privkey_blob_len, *pubkey_blob_len, privkey_blob, pubkey_blob);
fprintf(fp, "Logging param ID: %i Oid %x : N: %i Q: %i P %i Padded N: %i D1: %i D2: %i D3: %i \n", P->id, P->OID, P->N, P->q, P->p, P->padded_N, P->d1, P->d2, P->d3);
if(!P || !privkey_blob_len || !pubkey_blob_len)
{
return PQNTRU_ERROR;
}
N = P->N;
padN = P->padded_N;
q = P->q;
p = P->p;
d1 = P->d1;
d2 = P->d2;
d3 = P->d3;
fprintf(fp, "Logging Local N: %i Q: %i P %i Padded N: %i D1: %i D2: %i D3: %i \n", N, q, p, padN, d1, d2, d3);
fclose(fp);
我使用的是 Fedora 23 x64,因此在 NTRUMLS-Sharp github 上上传的当前 libntrumls.so 是在添加该片段的情况下编译的。
C# 控制台的输出
Param N: 743
Param P: 3
Param D1: 11
Param D2: 11
Param D3: 15
Result: -1 Private Key BLob Length: 0 Public Key Blob Lengh: 0
We got problems
We got problems
Result: -1 Private Key BLob Length: 3 Public Key Blob Lengh: 11
Generated Keys!
来自 log.txt
的输出
Logging made it here variables priv_blob_len_pointer -923442424 pub_blob_len_pointer -923442432 priv_blob_len -994004096 pub_blob_len -994004064 privkey c8f56510 pubkey f0b0b
Logging param ID: 3 Oid c8f56528 : N: 0 Q: 42678032 P 19 Padded N: 0 D1: 11 D2: 0 D3: 0
Logging Local N: 0 Q: 42678032 P 19 Padded N: 0 D1: 11 D2: 0 D3: 0
Logging made it here variables priv_blob_len_pointer -923442424 pub_blob_len_pointer -923442432 priv_blob_len -994003392 pub_blob_len -994003352 privkey c8f56510 pubkey f0b0b
Logging param ID: 3 Oid c8f56528 : N: 0 Q: 42678032 P 19 Padded N: 0 D1: 11 D2: 0 D3: 0
Logging Local N: 0 Q: 42678032 P 19 Padded N: 0 D1: 11 D2: 0 D3: 0
编辑:
另一个需要注意的有趣的事情是参数 ID 记录为 3 是正确的,因为枚举 Xxx20140508743
是 3,而 D1 是正确的 11。但是每次我 运行 函数记录的 OID 输出是不同的,当它是我的 ParamSet.Xxx20140508_743
中的一组 3 字节数组时。这使我相信错误出在封送处理 const char *name
中,这会导致其余部分中断。
下面是 log.txt 的另一个输出用于比较(这也是在 Marshal.StringToHGlobalAuto("Xxx20140508743[=34=]")
中添加了“\0”
Logging made it here variables priv_blob_len_pointer 982750168 pub_blob_len_pointer 982750160 priv_blob_len -960449664 pub_blob_len -960449632 privkey 3a9395e0 pubkey f0b0b
Logging param ID: 3 Oid 3a9395f8 : N: 0 Q: 38160144 P 19 Padded N: 0 D1: 11 D2: 0 D3: 0
Logging Local N: 0 Q: 38160144 P 19 Padded N: 0 D1: 11 D2: 0 D3: 0
Logging made it here variables priv_blob_len_pointer 982750168 pub_blob_len_pointer 982750160 priv_blob_len -960448960 pub_blob_len -960448920 privkey 3a9395e0 pubkey f0b0b
Logging param ID: 3 Oid 3a9395f8 : N: 0 Q: 38160144 P 19 Padded N: 0 D1: 11 D2: 0 D3: 0
Logging Local N: 0 Q: 38160144 P 19 Padded N: 0 D1: 11 D2: 0 D3: 0
我认为 Windows dll 还不能正常工作。如果有人不能立即在我的代码或错误日志中看到问题,编译和测试所有内容的说明都在 NTRUMLS C# 自述文件中。
感谢您抽出宝贵时间阅读此问题!我知道它很长且具有描述性,但我不太确定如何在不提供所有信息的情况下缩小它的范围,因为我花了很多时间搜索论坛并修改我的代码才能做到这一点。
此致
现在一切正常!
编组 params 结构如下所示
IntPtr parameter = Marshal.AllocHGlobal(Marshal.SizeOf(param));
Marshal.StructureToPtr(param, parameter, false);
下面是最终的函数。
public static KeyPair generate_keys(ParamSet param) {
uint pub_len = 0;
uint priv_len = 0;
IntPtr privkey_blob_len = new IntPtr(priv_len);
IntPtr pubkey_blob_len = new IntPtr(pub_len);
IntPtr parameter = Marshal.AllocHGlobal(Marshal.SizeOf(param));
Marshal.StructureToPtr(param, parameter, false);
IntPtr pv_ptr = IntPtr.Zero;
IntPtr pb_ptr = IntPtr.Zero;
var result = ffi.ffi.pq_gen_key(parameter, out privkey_blob_len, pv_ptr, out pubkey_blob_len, pb_ptr);
Console.WriteLine("Result: " + result + " Private Key BLob Length: " + privkey_blob_len.ToInt32() + " Public Key Blob Lengh: " + pubkey_blob_len);
if (result != 0)
Console.WriteLine("We got problems");
pv_ptr = Marshal.AllocHGlobal(privkey_blob_len.ToInt32());
pb_ptr = Marshal.AllocHGlobal(pubkey_blob_len.ToInt32());
result = ffi.ffi.pq_gen_key(parameter, out privkey_blob_len, pv_ptr, out pubkey_blob_len, pb_ptr);
if (result != 0)
Console.WriteLine("We got problems");
Console.WriteLine("Result: " + result.ToString() + " Private Key BLob Length: " + privkey_blob_len + " Public Key Blob Lengh: " + pubkey_blob_len);
byte[] privkeyBytes = new byte[privkey_blob_len.ToInt32()];
byte[] pubkeyBytes = new byte[pubkey_blob_len.ToInt32()];
Marshal.Copy(pv_ptr, privkeyBytes, 0, privkey_blob_len.ToInt32());
Marshal.Copy(pb_ptr, pubkeyBytes, 0, pubkey_blob_len.ToInt32());
Marshal.FreeHGlobal(pv_ptr);
Marshal.FreeHGlobal(pb_ptr);
Marshal.FreeHGlobal(parameter);
return new KeyPair(new PrivateKey(privkeyBytes), new PublicKey(pubkeyBytes));
}
还有我的 ffi
public static class ffi {
[DllImport("ntrumls")]
public static extern int pq_gen_key(IntPtr p, out IntPtr privkey_blob_len, IntPtr privkey_blob, out IntPtr pubkey_blob_len, IntPtr pubkey_blob);
}
我目前正在编写一个 NTRUMLS C# wrapper for the NTRUMLS C 库。我正在 运行 遇到一个问题,我认为我没有通过映射到 C 库入口点的外部函数接口正确地编组参数数据。
这是我在ffi.cs
.
using System;
using System.Runtime.InteropServices;
using NTRUMLS.Params;
namespace NTRUMLS.ffi {
public static class ffi {
[DllImport("ntrumls")]
public static extern int pq_gen_key(ParamSet p, out IntPtr privkey_blob_len, out byte[] privkey_blob, out IntPtr pubkey_blob_len, out byte[] pubkey_blob);
}
}
我传入的特定 ParamSet 结构 param.cs
,我认为这可能是导致问题的具体原因。
using System;
using System.Text;
using System.Runtime.InteropServices;
namespace NTRUMLS.Params {
[SerializableAttribute]
[ComVisibleAttribute(true)]
public enum ParamSetId {
Xxx20140508401,
Xxx20140508439,
Xxx20140508593,
Xxx20140508743,
Xxx20151024401,
Xxx20151024443,
Xxx20151024563,
// Xxx20151024509,
Xxx20151024743,
Xxx20151024907,
}
[StructLayout(LayoutKind.Sequential)]
public struct ParamSet {
ParamSetId id;
IntPtr name;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
byte[] oid;
[MarshalAs(UnmanagedType.U1)]
byte n_bits;
[MarshalAs(UnmanagedType.U1)]
byte q_bits;
[MarshalAs(UnmanagedType.U2)]
ushort n;
[MarshalAs(UnmanagedType.I1)]
sbyte p;
[MarshalAs(UnmanagedType.I8)]
long q;
[MarshalAs(UnmanagedType.I8)]
long b_s;
[MarshalAs(UnmanagedType.I8)]
long b_t;
[MarshalAs(UnmanagedType.I8)]
long norm_bound_s;
[MarshalAs(UnmanagedType.I8)]
long norm_bound_t;
[MarshalAs(UnmanagedType.U1)]
byte d1;
[MarshalAs(UnmanagedType.U1)]
byte d2;
[MarshalAs(UnmanagedType.U1)]
byte d3;
[MarshalAs(UnmanagedType.U2)]
ushort padded_n;
public ushort get_n() {
return n;
}
public sbyte get_p() {
return p;
}
public byte get_d1() {
return d1;
}
public byte get_d2() {
return d2;
}
public byte get_d3() {
return d3;
}
public uint product_form_bytes() {
return (uint)(4 * (d1 + d2 + d3));
}
public uint polynomial_bytes() {
return (uint)(padded_n * 8);
}
public uint privkey_packed_bytes() {
return (uint)(5 + 2 * ((2 * ( d1 + d2 + d3) * n_bits + 7) / 8) + ((n +4) / 5));
}
public uint pubkey_packed_bytes() {
return (uint)(5 + (n * q_bits + 7) / 8 + 64);
}
public ParamSet (ParamSetId ID, IntPtr NAME, byte[] OID, byte N_BITS, byte Q_BITS, ushort N, sbyte P, long Q, long B_S, long B_T, long NORM_BOUND_S, long NORM_BOUND_T, byte D1, byte D2, byte D3, ushort PADDED_N) {
id = ID;
name = NAME;
oid = OID;
n_bits = N_BITS;
q_bits = Q_BITS;
n = N;
p = P;
q = Q;;
b_s = B_S;
b_t = B_T;
norm_bound_s = NORM_BOUND_S;
norm_bound_t = NORM_BOUND_T;
d1 = D1;
d2 = D2;
d3 = D3;
padded_n = PADDED_N;
}
}
public static class ParamSets {
/// <summary>
/// 256 bit security parameter
/// </summary>
public static readonly ParamSet Xxx20140508_743 = new ParamSet(
ParamSetId.Xxx20140508743,
Marshal.StringToHGlobalAuto("Xxx20140508743"),
new byte[] {0xff, 0xff, 0xfc},
10,
20,
743,
3,
1 << 20,
336,
112,
(1 << 19) - 336,
(1 << 19) - 112,
11,
11,
15,
768);
}
}
这是包装器本身 NTRUMLSWrapper.cs
。
using NTRUMLS.ffi;
using NTRUMLS.Params;
using System;
using System.Runtime.InteropServices;
namespace NTRUMLS.Library {
public static class NTRUMLSWrapper {
public static KeyPair generate_keys(ParamSet param) {
int pub_len = 0;
int priv_len = 0;
Console.WriteLine("Param N: " + param.get_n());
Console.WriteLine("Param P: " + param.get_p());
Console.WriteLine("Param D1: " + param.get_d1());
Console.WriteLine("Param D2: " + param.get_d2());
Console.WriteLine("Param D3: " + param.get_d3());
GCHandle pub_len_handle = GCHandle.Alloc(pub_len);
GCHandle priv_len_handle = GCHandle.Alloc(priv_len);
IntPtr privkey_blob_len = (IntPtr)pub_len_handle;
IntPtr pubkey_blob_len = (IntPtr)priv_len_handle;
GCHandle handle = GCHandle.Alloc(param);
IntPtr paramater = (IntPtr)handle;
byte[] pv = new byte[priv_len];
byte[] pb = new byte[pub_len];
// GCHandle pv_handle = GCHandle.Alloc(pv);
// GCHandle pb_handle = GCHandle.Alloc(pb);
var result = ffi.ffi.pq_gen_key(param, out privkey_blob_len, out pv, out pubkey_blob_len, out pb);
Console.WriteLine("Result: " + result + " Private Key BLob Length: " + priv_len + " Public Key Blob Lengh: " + pub_len);
if (result != 0)
Console.WriteLine("We got problems");
byte[] privatekey_blob = new byte[privkey_blob_len.ToInt64()];
byte[] pubkey_blob = new byte[pubkey_blob_len.ToInt64()];
result = ffi.ffi.pq_gen_key(param, out privkey_blob_len, out privatekey_blob, out pubkey_blob_len, out pubkey_blob);
if (result != 0)
Console.WriteLine("We got problems");
Console.WriteLine("Result: " + result.ToString() + " Private Key BLob Length: " + privkey_blob_len + " Public Key Blob Lengh: " + pubkey_blob_len);
// byte[] privkeyBytes = new byte[priv_len.ToInt32()];
// byte[] pubkeyBytes = new byte[pub_len.ToInt32()];
return new KeyPair(new PrivateKey(pubkey_blob), new PublicKey(privatekey_blob));;
}
}
public struct PrivateKey {
byte[] ffi_key;
public PrivateKey (byte[] bytes) {
ffi_key = bytes;
}
public byte[] get_bytes() {
return ffi_key;
}
}
public struct PublicKey {
byte[] ffi_key;
public PublicKey (byte[] bytes) {
ffi_key = bytes;
}
public byte[] get_bytes() {
return ffi_key;
}
}
public struct KeyPair {
PublicKey publicKey;
PrivateKey privateKey;
public KeyPair(PrivateKey privKey, PublicKey pubkey)
{
publicKey = pubkey;
privateKey = privKey;
}
public PublicKey getPublic()
{
return publicKey;
}
public PrivateKey getPrivate()
{
return privateKey;
}
}
}
并且 Program.cs
到 运行 密钥生成测试。
using System;
using NTRUMLS.Library;
using NTRUMLS.Params;
namespace NTRUMLS
{
public class Program
{
public static void Main(string[] args)
{
KeyPair keypair = NTRUMLSWrapper.generate_keys(ParamSets.Xxx20140508_743);
Console.WriteLine("Generated Keys!");
// TODO Sign, than Verify to confirm test
}
}
}
这是我编组到的 C 函数的头函数
在pqntrusign.h
int
pq_gen_key(
PQ_PARAM_SET *params,
size_t *privkey_blob_len,
unsigned char *privkey_blob,
size_t *pubkey_blob_len,
unsigned char *pubkey_blob);
在 params.h
和 params.c
enum _PQ_PARAM_SET_ID {
XXX_20140508_401,
XXX_20140508_439,
XXX_20140508_593,
XXX_20140508_743,
XXX_20151024_401,
XXX_20151024_443,
XXX_20151024_563,
//XXX_20151024_509,
XXX_20151024_743,
XXX_20151024_907,
};
struct _PQ_PARAM_SET {
PQ_PARAM_SET_ID id; /* parameter set id */
const char *name; /* human readable name */
const uint8_t OID[3]; /* OID */
uint8_t N_bits; /* ceil(log2(N)) */
uint8_t q_bits; /* ceil(log2(q)) */
uint16_t N; /* ring degree */
int8_t p; /* message space prime */
int64_t q; /* ring modulus */
int64_t B_s; /* max norm of f*a convolution */
int64_t B_t; /* max norm of g*a convolution */
int64_t norm_bound_s;/* q/2 - B_s */
int64_t norm_bound_t;/* q/2 - B_t */
uint8_t d1; /* Product form +1/-1 counts */
uint8_t d2;
uint8_t d3;
uint16_t padded_N; /* # Polynomial coefficients for Karatsuba */
};
我认为当前的问题是 ParamSet struct
,以及将名称属性与 C 结构 const char*name
指针属性正确匹配。但是,我不完全确定是这样。
我修改了 NTRUMLS C pqntrusign.c
源文件以打印到 log.txt 并记录我传递的变量。这是我在 int pq_gen_key
函数开头添加的片段。
FILE * fp;
fp = fopen ("log.txt", "a+");
fprintf(fp, "Logging made it here variables priv_blob_len_pointer %i pub_blob_len_pointer %i priv_blob_len %i pub_blob_len %i privkey %x pubkey %x \n", privkey_blob_len, pubkey_blob_len, *privkey_blob_len, *pubkey_blob_len, privkey_blob, pubkey_blob);
fprintf(fp, "Logging param ID: %i Oid %x : N: %i Q: %i P %i Padded N: %i D1: %i D2: %i D3: %i \n", P->id, P->OID, P->N, P->q, P->p, P->padded_N, P->d1, P->d2, P->d3);
if(!P || !privkey_blob_len || !pubkey_blob_len)
{
return PQNTRU_ERROR;
}
N = P->N;
padN = P->padded_N;
q = P->q;
p = P->p;
d1 = P->d1;
d2 = P->d2;
d3 = P->d3;
fprintf(fp, "Logging Local N: %i Q: %i P %i Padded N: %i D1: %i D2: %i D3: %i \n", N, q, p, padN, d1, d2, d3);
fclose(fp);
我使用的是 Fedora 23 x64,因此在 NTRUMLS-Sharp github 上上传的当前 libntrumls.so 是在添加该片段的情况下编译的。
C# 控制台的输出
Param N: 743
Param P: 3
Param D1: 11
Param D2: 11
Param D3: 15
Result: -1 Private Key BLob Length: 0 Public Key Blob Lengh: 0
We got problems
We got problems
Result: -1 Private Key BLob Length: 3 Public Key Blob Lengh: 11
Generated Keys!
来自 log.txt
的输出Logging made it here variables priv_blob_len_pointer -923442424 pub_blob_len_pointer -923442432 priv_blob_len -994004096 pub_blob_len -994004064 privkey c8f56510 pubkey f0b0b
Logging param ID: 3 Oid c8f56528 : N: 0 Q: 42678032 P 19 Padded N: 0 D1: 11 D2: 0 D3: 0
Logging Local N: 0 Q: 42678032 P 19 Padded N: 0 D1: 11 D2: 0 D3: 0
Logging made it here variables priv_blob_len_pointer -923442424 pub_blob_len_pointer -923442432 priv_blob_len -994003392 pub_blob_len -994003352 privkey c8f56510 pubkey f0b0b
Logging param ID: 3 Oid c8f56528 : N: 0 Q: 42678032 P 19 Padded N: 0 D1: 11 D2: 0 D3: 0
Logging Local N: 0 Q: 42678032 P 19 Padded N: 0 D1: 11 D2: 0 D3: 0
编辑:
另一个需要注意的有趣的事情是参数 ID 记录为 3 是正确的,因为枚举 Xxx20140508743
是 3,而 D1 是正确的 11。但是每次我 运行 函数记录的 OID 输出是不同的,当它是我的 ParamSet.Xxx20140508_743
中的一组 3 字节数组时。这使我相信错误出在封送处理 const char *name
中,这会导致其余部分中断。
下面是 log.txt 的另一个输出用于比较(这也是在 Marshal.StringToHGlobalAuto("Xxx20140508743[=34=]")
Logging made it here variables priv_blob_len_pointer 982750168 pub_blob_len_pointer 982750160 priv_blob_len -960449664 pub_blob_len -960449632 privkey 3a9395e0 pubkey f0b0b
Logging param ID: 3 Oid 3a9395f8 : N: 0 Q: 38160144 P 19 Padded N: 0 D1: 11 D2: 0 D3: 0
Logging Local N: 0 Q: 38160144 P 19 Padded N: 0 D1: 11 D2: 0 D3: 0
Logging made it here variables priv_blob_len_pointer 982750168 pub_blob_len_pointer 982750160 priv_blob_len -960448960 pub_blob_len -960448920 privkey 3a9395e0 pubkey f0b0b
Logging param ID: 3 Oid 3a9395f8 : N: 0 Q: 38160144 P 19 Padded N: 0 D1: 11 D2: 0 D3: 0
Logging Local N: 0 Q: 38160144 P 19 Padded N: 0 D1: 11 D2: 0 D3: 0
我认为 Windows dll 还不能正常工作。如果有人不能立即在我的代码或错误日志中看到问题,编译和测试所有内容的说明都在 NTRUMLS C# 自述文件中。
感谢您抽出宝贵时间阅读此问题!我知道它很长且具有描述性,但我不太确定如何在不提供所有信息的情况下缩小它的范围,因为我花了很多时间搜索论坛并修改我的代码才能做到这一点。
此致
现在一切正常!
编组 params 结构如下所示
IntPtr parameter = Marshal.AllocHGlobal(Marshal.SizeOf(param));
Marshal.StructureToPtr(param, parameter, false);
下面是最终的函数。
public static KeyPair generate_keys(ParamSet param) {
uint pub_len = 0;
uint priv_len = 0;
IntPtr privkey_blob_len = new IntPtr(priv_len);
IntPtr pubkey_blob_len = new IntPtr(pub_len);
IntPtr parameter = Marshal.AllocHGlobal(Marshal.SizeOf(param));
Marshal.StructureToPtr(param, parameter, false);
IntPtr pv_ptr = IntPtr.Zero;
IntPtr pb_ptr = IntPtr.Zero;
var result = ffi.ffi.pq_gen_key(parameter, out privkey_blob_len, pv_ptr, out pubkey_blob_len, pb_ptr);
Console.WriteLine("Result: " + result + " Private Key BLob Length: " + privkey_blob_len.ToInt32() + " Public Key Blob Lengh: " + pubkey_blob_len);
if (result != 0)
Console.WriteLine("We got problems");
pv_ptr = Marshal.AllocHGlobal(privkey_blob_len.ToInt32());
pb_ptr = Marshal.AllocHGlobal(pubkey_blob_len.ToInt32());
result = ffi.ffi.pq_gen_key(parameter, out privkey_blob_len, pv_ptr, out pubkey_blob_len, pb_ptr);
if (result != 0)
Console.WriteLine("We got problems");
Console.WriteLine("Result: " + result.ToString() + " Private Key BLob Length: " + privkey_blob_len + " Public Key Blob Lengh: " + pubkey_blob_len);
byte[] privkeyBytes = new byte[privkey_blob_len.ToInt32()];
byte[] pubkeyBytes = new byte[pubkey_blob_len.ToInt32()];
Marshal.Copy(pv_ptr, privkeyBytes, 0, privkey_blob_len.ToInt32());
Marshal.Copy(pb_ptr, pubkeyBytes, 0, pubkey_blob_len.ToInt32());
Marshal.FreeHGlobal(pv_ptr);
Marshal.FreeHGlobal(pb_ptr);
Marshal.FreeHGlobal(parameter);
return new KeyPair(new PrivateKey(privkeyBytes), new PublicKey(pubkeyBytes));
}
还有我的 ffi
public static class ffi {
[DllImport("ntrumls")]
public static extern int pq_gen_key(IntPtr p, out IntPtr privkey_blob_len, IntPtr privkey_blob, out IntPtr pubkey_blob_len, IntPtr pubkey_blob);
}