php中openssl函数

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/

点赞(4) 打赏

评论列表 共有 1 条评论

情话烫心 1年前 回复TA

新年到,红运当头照,祝愿你在新的一年里,工作顺利,大展红图;生活幸福,红红火火!新新年快乐!

立即
投稿
发表
评论
返回
顶部