3

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

任何有关如何使用它来获取共享密钥的示例将不胜感激!

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

4

1 回答 1

4

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

我绝不是密码学专家,但我认为您应该使用RFC 2412 - The OAKLEY Key Determination Protocol (appendix E.1)中定义的“知名组”或RFC 3526中的组。在将它们与Zend_Crypt_DiffieHellman.

您应该使用哪个组?

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

取决于您计划如何实施密钥交换。如果您必须对每个 HTTP 请求执行 DH-exchange,那么更大的组将杀死您的服务器,因为计算需要更多时间(但另一方面更难破解)。在我的示例中,我使用了 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 库都允许您检查服务器证书,因此请检查客户端上服务器证书的有效性(至少检查指纹)。

如果您需要或希望您可以检查服务器上的客户端证书(请参阅将 SSL 客户端证书与 PHP 一起使用)。

于 2012-02-08T10:56:36.910 回答