在PHP中实现的简单加密问题

时间:2009-04-17 21:10:06

标签: php cryptography

我需要实现一些符合以下条件的功能:

  1. function genKey:给定一个字符串q(这可能是MD5或SHA哈希)和种子字符串,该函数必须生成一个新的字符串p

  2. function checkKey:如果从字符串q生成字符串p(使用上一个函数),则此函数必须返回true

  3. 在seudo-code中,上面的内容就是这样:

    p=genKey(q,seed) ; // generate string p from q and seed 
    
    checkKey(p,q)==true ; // if p was generated from q, then this must return true. False otherwise.
    

    有没有人知道做这种事情的现有算法? 如果没有已知的PHP实现,我可以自己实现算法,所以我真正要求的是完成此过程的过程。

6 个答案:

答案 0 :(得分:4)

听起来你可能正试图描述MAC。

消息验证代码采用消息摘要,秘密和消息。秘密和数据被一起散列,结果包含在消息中。

知道秘密的消息接收者可以执行相同的摘要计算,并将其MAC与伴随接收消息的MAC进行比较。如果他们是平等的,他可以相信信息没有改变。


鉴于您的意见,我现在明白您正在使用非对称密钥,而不是秘密密钥,它将在MAC中使用。

然而,仍有一点混乱。通常,私有签名密钥由其所有者保密,在这种情况下似乎是客户端。客户端可以加密证明他们拥有与公钥对应的私钥而不泄露私钥。

使用数字签名,您可以执行以下操作:

p = genKey(pvt, seed)
checkKey(pub, p)

此处,pvt是服务器的私钥,pub是其公钥。 seed参数是签名的数据。如果我理解您的应用程序(我怀疑),seed应该是客户端标识符。然后p是一种将seed及其签名捆绑在一起的邮件格式。您的问题很混乱,因为q用于生成和验证p - 就像共享密钥一样。

但是,此方案(或MAC方案)中没有任何内容可以阻止一个客户端使用另一个客户端的p值。使用这种技术所能做的就是确保消息内容没有被更改。例如,如果消息类似于“clientID = Alice,IPAddress = 192.168.1.1”,则可以确保Mallory没有将自己的IP地址替换为Alice的。

但如果消息只是“clientID = Alice”,则无法阻止Alice向Bob提供防篡改消息(以换取分割许可证的费用),而您无法控制Mallory是否破解进入爱丽丝的盒子并窃取信息。

顺便说一句,如果消息完整性确实是您所需要的,并且您可以轻松地在发送方和接收方之间共享秘密,则MAC与公钥加密相比具有一些优势,例如更小的消息大小和更快的性能

概述您要防范的威胁。密码学很难。设计未经验证的计划通常会很糟糕。

答案 1 :(得分:2)

对于这个讨论,让p == hash(q)

然后,您可以轻松地使用OpenSSL和php通过私钥对“p”进行签名,并将该签名保留在“p”旁边。

然后使用OpenSSL验证功能使用与您的私钥配对的公钥检查签名的'p'是很简单的。在这种情况下,'p'将是要验证的数据。

有关在php中使用OpenSSL签名和验证数据的信息和示例,请参阅openssl_signopenssl_verify

答案 2 :(得分:1)

您可以使用crypt()hash()md5()

编辑: 我不介意downvote。看看其他答案的复杂性,我一定是误解了这个问题。但如果人们会在评论中附上他们的评价,这样我会至少知道我的答案有什么问题。这将是一件好事。

我从问题中收集到的是提问者想要实现类似的东西:

function genKey($q, $seed) {
  // assuming $seed is a properly formatted md5/sha salt
  return crypt($q, $seed);
}

function checkKey($p, $q, $seed) {
  return ($p == genKey($q, $seed));
}

我认为PHP的单向加密函数中的任何一个都可用于实现此目的,这是错误的吗?

答案 3 :(得分:1)

您可以尝试这样的事情:

$p = genKey($q,rand());
checkKey($p,$q) == true;


function genkey($q,$seed)
{
    if(array_search($_SESSION['seeds'],$seed) === FALSE)
    {
        $_SESSION['seeds'][] = $seed;
    }
    return hash("sha512", $q . $seed);
}

function checkKey($p,$q)
{
    $returnVal = false;
    foreach($_SESSION['seeds'] AS $s)
    {
        if(hash("sha512", $q . $s) == $p)
        {
            $returnVal = true;
            break;
        }
    }
    return $returnVal;
}

当然,我会推荐其他用于存储有效种子的东西,但这仅仅是一个概念证据。

答案 4 :(得分:1)

好的,你所指的是公钥加密的原则,特别是创建签名。它遵循复杂的数学原则(您必须实施)。

在基本RSA签名中,您可以通过应用以下数学创建签名 s

s = m^d % n

m 是消息(或者字符串q), d 是私钥, n 是模数(在私人和公共密钥)。

然后可以通过这个数学验证:

 m = s^e % n

e 是公钥。

当然,必须根据特定的数学标准生成密钥才能使其生效。有时候钥匙会变得很大。同样,所有这些都是通过整数完成的,因此您必须将文本转换为十进制并返回。

有关更多信息和更多数学,请查看this page.

编辑:我想我应该提一下为什么要使用公钥加密。基本上,它可以防止两件事:信息是可以验证的,不能伪造。

答案 5 :(得分:0)

检查方是否可以访问种子?如果种子可以在检查端保持安全(就像在Web应用程序上那样),您可以轻松地使用MD Digest身份验证,使用MD5。

伪代码:

   function genKey(q) {
      p = md5sum(q . ':' . seed);
      return p;
   }

   function checkKey(p,q) {
      return md5sum(q . ':' . seed) == p;
   }

如果您需要第二方验证“签名”,那么您可能只想使用PKI。