Zend_Crypt_DiffieHellman - 使用示例

时间:2012-02-07 13:01:08

标签: zend-framework cryptography diffie-hellman

是否有使用Zend_Crypt_DiffieHellman类的示例?我正在尝试编写一个桌面应用程序,它将以安全的方式与Zend Framework上的PHP服务器通信。我坚持不知道如何在双方之间建立共享密钥。我需要获得一组自己的素数吗?

非常感谢如何使用它来获取共享密钥的任何示例!

我认为我真正的问题是如何为它获得素数和生成器!

1 个答案:

答案 0 :(得分:4)

如何获取一个组(由素数和生成器组成)

我绝不是加密专家,但我认为您应该使用RFC 2412 - The OAKLEY Key Determination Protocol (appendix E.1)中定义的“知名群组”或RFC 3526中的群组。在将{十六进制数与Zend_Crypt_DiffieHellman一起使用之前,您可能必须先将十六进制数转换为十进制数。

您应该使用哪个组?

越大越好 - 不,只是开玩笑。

取决于您计划如何实施密钥交换。如果你必须在每个HTTP请求上执行DH交换,一个更大的组将杀死你的服务器,因为它需要更多的时间来计算(但另一方面更难破解)。在我的例子中,我使用了768位的“众所周知的组1”并且它相当慢(好吧我的开发机器不是最快的)。

您还可以在第一步中添加服务器和客户端同意使用的预定义组的选项。例如:您使用您的应用程序提供众所周知的组1,2和5。在实际的DH密钥交换之前,您的各方同意使用第1组进行实际的DH密钥交换。这样,当硬件赶上时,您可以切换到更大的组。当然,这个小组协议为你的密钥交换过程增加了另一个步骤。

Zend_Crypt_DiffieHellman示例

这是一个简单的例子,没有实际将公共数据传输到另一个进程。

// why disable the use of openssl?
// apparently "computeSecretKey" uses the php function 
// openssl_dh_compute_key which expects an openssl "pkey" resource but
// the Zend Framework (1.11.4) supplies a string
Zend_Crypt_DiffieHellman::$useOpenssl = false;

// here I define the Well Known Group 1 (which consists of the prime and
// the generator) with a 768 bit prime. 
// These can be either hard coded ore your parties agree on which group to
// use in a separate step of the key-exchange process.
$public_prime =
    "155251809230070893513091813125848175563133404943451431320235" .
    "119490296623994910210725866945387659164244291000768028886422" .
    "915080371891804634263272761303128298374438082089019628850917" .
    "0691316593175367469551763119843371637221007210577919";
$public_generator = 2;

// if you want it to go fast use smaller values (these are from the
// Diffie Hellman entry on Wikipedia).
//$public_generator = 5;
//$public_prime = 23;

$bob = new Zend_Crypt_DiffieHellman($public_prime, $public_generator);
$alice = new Zend_Crypt_DiffieHellman($public_prime, $public_generator);

// first generate the private key and the public data on both sides
$bob->generateKeys();
$alice->generateKeys();

// you can access the public data using the "getPublicKey" method.
// You can transmit those values over the wire to the other party. 
echo "bob=", $bob->getPublicKey(), PHP_EOL;
echo "alice=", $alice->getPublicKey(), PHP_EOL;

// After both parties have received the public data from the other party
// they can calculate the shared secret:    
echo "shared(alice)=", $alice->computeSecretKey($bob->getPublicKey()), PHP_EOL;
echo "shared(bob  )=", $bob->computeSecretKey($alice->getPublicKey()), PHP_EOL;
// the values should be equal.

唯一真正通过网络传递的是Zend_Crypt_DiffieHellman::getPublicKey的返回值。公共数据可以编码为文本(Zend_Crypt_DiffieHellman::NUMBER)或二进制数据(Zend_Crypt_DiffieHellman::BINARY)。

还有另一个:Zend_Crypt_DiffieHellman::BTWOC与二进制文件相同但前导零字节,因此如果客户端应用程序使用Java JCE或.NET,则整数不会被视为“已签名”整数Crypto API这个可能是二进制传输的最佳选择。

未经请求的建议

如果您想让自己的生活更轻松,不要重新发明SSL - 只需通过HTTPS使用现有的SSL实施。

大多数SSL库允许您检查服务器证书,因此请检查客户端上服务器证书的有效性(至少检查指纹)。

如果您需要或想要,可以在服务器上查看客户端的证书(请参阅Using SSL Client Certificates with PHP)。