OpenSSL是一个广泛应用于安全领域的开源软件包,可以实现安全通信、证书交换、数字签名以及密码学原语等等功能。在PHP中,也提供了丰富的OpenSSL函数,开发人员可以方便地利用这些函数来实现各种安全相关的操作,例如:加密、解密、签名、验签、生成密钥、导入/导出证书、SSL/TLS握手等等。
本文将介绍PHP中常见的OpenSSL函数,并以实际代码演示为例,帮助开发人员更加深入地理解OpenSSL的使用方法。
1. OpenSSL函数的使用
在使用OpenSSL函数之前,需要确保PHP编译时已经包含OpenSSL扩展,可在php.ini文件中确认是否已经启用openssl扩展。
```ini
extension=openssl
```
在终端中可以使用php -m | grep openssl 命令验证是否开启了此扩展
在代码中,使用OpenSSL函数前需要使用 openssl_ 函数检查是否有OpenSSL扩展支持:
```php
if (!extension_loaded('openssl')) {
echo 'OpenSSL扩展未加载!';
exit;
}
```
在验证OpenSSL扩展存在后,就可以开始使用OpenSSL函数了。
以下是OpenSSL中常见的函数:
- openssl_encrypt(): 对数据进行加密
- openssl_decrypt(): 对数据进行解密
- openssl_pkey_new(): 生成新的密钥对
- openssl_pkey_export_to_file(): 导出密钥对到文件
- openssl_pkey_get_private(): 从文件中载入私钥
- openssl_pkey_get_public(): 从文件中载入公钥
- openssl_sign(): 对数据进行签名
- openssl_verify(): 对数据进行验签
- openssl_csr_new(): 生成证书签名请求
- openssl_csr_sign(): 签发证书签名请求
- openssl_x509_export_to_file(): 导出证书到文件
- openssl_x509_read(): 从文件中载入证书
下面我们将依次介绍这些函数的具体使用方法。
2. 数据的加密和解密
OpenSSL可以对数据进行加密和解密,其中使用了对称密钥加密和非对称密钥加密,前者更加高效,后者更加安全。
对称密钥加密的方式中,使用一个密钥同时对明文和密文进行加密和解密。我们通常会使用AES算法进行这种加密方式。下面是一个对称加密的示例:
```php
// 加密数据
function encryptData($data, $key) {
$ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
$iv = openssl_random_pseudo_bytes($ivlen);
$ciphertext_raw = openssl_encrypt($data, $cipher, $key, $options=OPENSSL_RAW_DATA, $iv);
$hmac = hash_hmac('sha256', $ciphertext_raw, $key, $as_binary=true);
$encrypted = base64_encode( $iv.$hmac.$ciphertext_raw );
return $encrypted;
}
// 解密数据
function decryptData($data, $key) {
$c = base64_decode($data);
$ivlen = openssl_cipher_iv_length($cipher="AES-128-CBC");
$iv = substr($c, 0, $ivlen);
$hmac = substr($c, $ivlen, $sha2len=32);
$ciphertext_raw = substr($c, $ivlen+$sha2len);
$original_plaintext = openssl_decrypt($ciphertext_raw, $cipher, $key, $options=OPENSSL_RAW_DATA, $iv);
$calcmac = hash_hmac('sha256', $ciphertext_raw, $key, $as_binary=true);
if (!hash_equals($hmac, $calcmac)) {
return false;
}
return $original_plaintext;
}
// 测试加密和解密
$key = '1234567890abcdef'; //长度为16的字符串
$data = 'Hello Open SSL!';
$encryptedData = encryptData($data, $key);
$decryptData = decryptData($encryptedData, $key);
echo '原始数据:'.$data.PHP_EOL;
echo '密文:'.$encryptedData.PHP_EOL;
echo '解密后的数据:'.$decryptData.PHP_EOL;
```
在代码中,我们首先定义了两个函数:encryptData()和decryptData()。第一个函数用于加密数据,使用AES-128-CBC算法,使用了OpenSSL提供的openssl_encrypt函数进行加密。
第二个函数用于解密数据,与加密函数相对应,使用openssl_decrypt函数进行解密。在解密过程中,也用到了校验码(HMAC)和哈希算法SHA256,以保证解密的数据的完整性和正确性。
3. 密钥的生成
在加密数据之前,常常需要生成密钥。以下是生成密钥的方法:
```php
$privateKey = openssl_pkey_new(); // 生成新的密钥对
openssl_pkey_export_to_file($privateKey, 'private.pem'); // 将私钥保存到文件
$publicKey = openssl_pkey_get_details($privateKey)['key']; // 获取公钥
file_put_contents('public.pem', $publicKey); // 将公钥保存到文件
```
在代码中,我们使用openssl_pkey_new函数生成新的密钥对。默认情况下,该函数会生成2048位的RSA密钥对。如果需要生成其他位数的密钥对,可以使用openssl_pkey_new的第二个参数,例如:
```php
$keyConfig = array(
'private_key_bits' => 4096
);
$privateKey = openssl_pkey_new($keyConfig); // 生成4096位的RSA密钥对
```
密钥对生成后,我们可以使用openssl_pkey_export_to_file函数将私钥保存到文件中,并使用openssl_pkey_get_details函数获取公钥。之后,我们将公钥保存到文件中。
需注意,在实际应用中,需要牢记私钥的安全性。将私钥保存在安全的地方,并且不要暴露私钥的内容。
4. 文件的加密和解密
对于文件的加密和解密,我们可以使用上述数据加密函数,并对文件内容进行读取、加密和写入操作。
以下是对文件进行加密和解密的代码示例:
```php
// 加密文件
function encryptFile($filePath, $key) {
$content = file_get_contents($filePath);
$encryptedContent = encryptData($content, $key);
file_put_contents($filePath, $encryptedContent);
}
// 解密文件
function decryptFile($filePath, $key) {
$content = file_get_contents($filePath);
$decryptedContent = decryptData($content, $key);
file_put_contents($filePath, $decryptedContent);
}
// 测试文件加密和解密
$key = '1234567890abcdef'; //长度为16的字符串
$filePath = 'test.txt';
file_put_contents($filePath, 'Hello Open SSL!');
encryptFile($filePath, $key);
decryptFile($filePath, $key);
echo '文件解密的结果:'.file_get_contents($filePath);
```
在代码中,我们首先定义了两个函数:encryptFile()和decryptFile(),对文件进行加密和解密操作。在加密和解密函数中,我们使用encryptData()和decryptData()函数对整个文件内容进行加密和解密操作,并使用file_put_contents()将结果写回到文件中。
需注意,在加密和解密一个大型文件时,需要将文件分块处理,并尽可能地减少内存占用,避免导致内存不足的情况。
5. 数字签名和验签
数字签名是保证消息完整性和身份验证的重要手段之一。在OpenSSL中,我们可以使用数字签名和验签函数,实现对数据的签名和验签操作。
数字签名的过程如下:
* 先使用 hash 函数对待签名数据进行哈希计算,生成一个哈希值
* 将哈希值使用私钥进行加密,得到签名信息
验签的过程如下:
* 使用相同的哈希算法对待验证数据计算哈希值,得到哈希值
* 使用公钥对签名信息进行解密,得到原始的哈希值
* 对比这两个哈希值是否相等
以下是数字签名和验签的示例代码:
```php
// 签名函数
function signData($data, $privateKeyFile) {
$privateKey = openssl_pkey_get_private(file_get_contents($privateKeyFile));
openssl_sign($data, $signature, $privateKey, OPENSSL_ALGO_SHA256);
return base64_encode($signature);
}
// 验签函数
function verifySign($data, $signature, $publicKeyFile) {
$publicKey = openssl_pkey_get_public(file_get_contents($publicKeyFile));
$result = openssl_verify($data, base64_decode($signature), $publicKey, OPENSSL_ALGO_SHA256);
return ($result == 1);
}
// 测试数字签名和验签
$privateKeyFile = 'private.pem';
$publicKeyFile = 'public.pem';
$data = 'Hello Open SSL!';
$signature = signData($data, $privateKeyFile);
echo '数字签名结果:'.$signature.PHP_EOL;
if (verifySign($data, $signature, $publicKeyFile)) {
echo '验签成功!';
} else {
echo '验签失败!';
}
```
在代码中,我们定义了两个函数:signData()和verifySign()。前者用于对数据进行签名,后者用于对数据进行验签。在签名和验签过程中,我们使用了SHA256哈希算法。在测试代码中,我们先对数据进行签名,然后使用验证函数进行验签,成功则输出“验签成功!”,失败则输出“验签失败!”。
6. 证书签名请求和签发
OpenSSL还提供了生成并签发证书的方法。下面是生成证书签名请求和签发证书的示例:
```php
// 生成证书签名请求
function createCSR(&$privateKey, $dn, $challengePassword = '',
$configFile = null, array $extensions = []) {
if (!$privateKey) {
$config = array(
'private_key_bits' => 2048,
'private_key_type' => OPENSSL_KEYTYPE_RSA
);
$privateKey = openssl_pkey_new($config);
}
$csrConfig = array('digest_alg' => 'SHA256');
if ($challengePassword) {
$csrConfig['challenge_password'] = $challengePassword;
}
if ($extensions) {
$csrConfig['req_extensions'] = $extensions;
}
$csr = openssl_csr_new($dn, $privateKey, $csrConfig);
openssl_csr_export($csr, $csrString);
return [$csrString, $privateKey];
}
// 签发证书
function issueCert(&$csrString, $duration, $caCert, $caPrivateKey) {
$csr = openssl_csr_get_sbject($csrString);
$config = array(
'digest_alg' => 'SHA256',
'x509_extensions' => 'v3_ca',
'req_extensions' => 'v3_req',
'serial_number' => openssl_random_pseudo_bytes(16),
'subject' => $csr,
'issuer' => openssl_x509_parse($caCert)['subject'],
'notBefore' => date('YmdHis'),
'notAfter' => date('YmdHis', strtotime('+'.$duration.' day'))
);
$x509 = openssl_csr_sign($csrString, $caCert, $caPrivateKey, $config, 0);
openssl_x509_export($x509, $certString);
return $certString;
}
// 测试证书签名请求和签发
$privateKey = null; // 为NULL表示要生成新的密钥
$csrSubject = array(
'countryName' => 'CN',
'stateOrProvinceName' => 'BJ',
'localityName' => 'BJ',
'organizationName' => 'OpenSSL Test',
'commonName' => 'OpenSSL Test Certificate'
);
$csrExtensions = array(
'subjectAltName' => 'DNS:example.cn'
);
$csrArray = createCSR($privateKey, $csrSubject, null, null, $csrExtensions);
$csrString = $csrArray[0];
$privateKey = $csrArray[1];
$caCert = file_get_contents('ca.crt');
$caPrivateKey = openssl_pkey_get_private(file_get_contents('ca.key'));
$certString = issueCert($csrString, 365, $caCert, $caPrivateKey);
echo $certString.PHP_EOL;
```
在代码中,我们定义了两个函数:createCSR() 和 issueCert()。前者用于生成签名请求,后者用于签发证书。
generateCertificateRequest()中,我们首先判断私钥是否为空,如果为空,则使用openssl_pkey_new函数生成新的2048位RSA密钥。然后,我们使用openssl_csr_new函数生成签名请求,并设置请求的参数等信息。之后,我们使用openssl_csr_export函数将签名请求导出到字符串中,并返回字符串和私钥。
在issueCert()中,我们使用openssl_x509_parse函数解析CA证书,并使用openssl_csr_get_subject函数获取证书主题信息。之后,我们使用openssl_csr_sign函数签发证书,签发时需要指定证书的有效期和签名信息等参数。
最终,我们使用openssl_x509_export函数将证书导出到字符串中,并输出。
以上是OpenSSL在PHP中的使用方法,开发人员可以根据实际需要,结合OpenSSL函数,完成更加复杂和安全的操作。同时,需要注意,使用OpenSSL操作过程中,需要充分了解加密操作的流程,确保操作过程中的数据的正确性和安全性。 如果你喜欢我们三七知识分享网站的文章, 欢迎您分享或收藏知识分享网站文章 欢迎您到我们的网站逛逛喔!https://www.ynyuzhu.com/
新年到,红运当头照,祝愿你在新的一年里,工作顺利,大展红图;生活幸福,红红火火!新新年快乐!