.NET中的长/大数和模数

时间:2009-10-12 20:57:33

标签: c# .net modulo

我目前正在编写一种快速自定义编码方法,其中我用一个数字标记一个密钥以验证它是否是有效密钥。

基本上我正在从编码中获取任何数字并将其乘以密钥。

然后,我会将这些数字乘以部署给购买密钥的用户/客户。我想简单地使用(Code%Key == 0)来验证密钥是否有效,但是对于较大的值,mod函数似乎没有按预期运行。

Number = 468721387; 键= 12345678; 代码=数字*密钥;

使用上面的数字: 代码%Key == 11418772

对于较小的数字,它会正确返回0.是否有一种可靠的方法来检查.NET中的长整数的可分性?

谢谢!

编辑: 好的,告诉我,如果我很特别并且遗漏了某些东西......

        long a = DateTime.Now.Ticks;
        long b = 12345;
        long c = a * b;
        long d = c % b;
        d == 10001 (Bad)

        long a = DateTime.Now.Ticks;
        long b = 12;
        long c = a * b;
        long d = c % b;
        d == 0 (Good)

我做错了什么?

4 个答案:

答案 0 :(得分:6)

正如其他人所说,你的问题是整数溢出。通过选中“高级构建设置”对话框中的“检查算术溢出/下溢”,可以使这一点更加明显。执行此操作时,执行* DateTime.Now.Ticks * 12345 *时,您将收到 OverflowException

一个简单的解决方案就是在代码中将“long”更改为“decimal”(或“double”)。

在.NET 4.0中,有一个新的BigInteger类。

最后,你说你是“......写一个快速的自定义编码方法......”,所以一个简单的自制解决方案可能满足你的需求。但是,如果这是生产代码,您可能会考虑更强大的涉及加密的解决方案或来自专门从事软件许可的第三方的解决方案。

答案 1 :(得分:5)

说整数溢出可能是罪魁祸首的答案几乎肯定是正确的;您可以通过在乘法周围放置一个“已检查”块并查看它是否会抛出异常来验证这一点。

但是这里有一个更大的问题,每个人似乎都在忽视。

最好的办法是向后退一步,重新考虑整个计划的智慧。您似乎正在尝试设计基于加密的安全系统,但您显然不是加密算法的专家。这是一个巨大的红色警告标志。 如果您需要基于加密的安全系统,请不要试图自己动手。有很多现成的加密系统由专家构建,经过严格测试并且随时可用。使用其中一个。

如果你实际上一心想推出自己的加密技术,那么以64位的方式计算数学是你最不担心的问题。 64位整数对于这个加密应用来说太小了。你需要使用更大的整数大小;否则,找到与代码匹配的密钥是微不足道的。

同样,我不能强烈强调构建正确的基于加密的安全代码是多么困难,这些代码实际上可以保护真实用户免受真正的威胁。

答案 2 :(得分:4)

整数溢出...请参阅我的评论。

您正在进行的乘法的值会溢出int数据类型并导致它换行(int值介于+/- 2147483647之间。)

选择一个更合适的数据类型来保存一个大到5786683315615386的值(乘法的结果)。

<强>更新

你的新例子改变了一些事情。

你使用的很长,但是现在你正在使用System.DateTime.Ticks,它在Mono上(不确定MS平台)正在返回633909674610619350。

当你将它乘以一个大数字时,你现在溢出long,就像之前溢出int一样。此时,您可能需要使用double来处理所需的值(decimal也可以使用,具体取决于乘数的大小)。

答案 3 :(得分:2)

显然,您的Code无法适应int数据类型。请尝试使用long

long code = (long)number * key;

(long)施法是必要的。如果没有强制转换,乘法将以32位整数形式完成(假设numberkey变量的类型为int),结果将被转换为long不是你想要的。通过将其中一个操作数强制转换为long,您可以告诉编译器对两个long数字执行乘法运算。