support/tests/Unit/RsaTest.php
yeyixianyang 2a35f36ec0 test(rsa): 重构并增强RSA测试用例
- 简化密钥对生成逻辑并重命名变量
- 新增私钥和公钥内容验证测试
- 新增证书内容验证测试
- 完善密钥格式化测试,增加BEGIN和END标记检查
- 新增证书格式化测试
- 添加无效密钥异常抛出测试
- 改进加密解密测试,使用更真实的消息内容
- 强化签名验证测试,增加篡改检测
- 新增解密失败异常测试
- 添加从证书获取公钥及相关信息的测试
- 创建ApplicationException、DomainException和JltxException异常类
2025-12-08 20:52:35 +08:00

149 lines
8.5 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace Jltx\Support\Tests\Unit;
use Jltx\Support\Security\RSA;
use RuntimeException;
beforeEach(function () {
// 生成一个测试用的密钥对
$keyPair = RSA::generateKeyPair();
$this->privateKeyString = $keyPair['private_key'];
$this->publicKeyString = $keyPair['public_key'];
// 获取密钥资源
$this->privateKey = RSA::getPrivateKey($this->privateKeyString);
$this->publicKey = RSA::getPublicKey($this->publicKeyString);
// 测试数据
$this->testMessage = 'This is a test message for RSA encryption and signing.';
});
it('can generate a key pair', function () {
$keyPair = RSA::generateKeyPair();
expect($keyPair)->toBeArray()
->and($keyPair)->toHaveKey('private_key')
->and($keyPair)->toHaveKey('public_key')
->and($keyPair['private_key'])->toBeString()
->and($keyPair['public_key'])->toBeString()
->and(RSA::validatePrivateKeyContent($keyPair['private_key']))->toBeTrue()
->and(RSA::validatePublicKeyContent($keyPair['public_key']))->toBeTrue();
});
it('can validate private key content', function () {
expect(RSA::validatePrivateKeyContent($this->privateKeyString))->toBeTrue()
->and(RSA::validatePrivateKeyContent('invalid private key'))->toBeFalse();
});
it('can validate public key content', function () {
expect(RSA::validatePublicKeyContent($this->publicKeyString))->toBeTrue()
->and(RSA::validatePublicKeyContent('invalid public key'))->toBeFalse();
});
it('can validate certificate content', function () {
// 有效的证书内容应该返回true无效的返回false
expect(RSA::validateCertificateContent('invalid cert content'))->toBeFalse();
});
it('can format private key', function () {
$formatted = RSA::privateKeyFormat($this->privateKeyString);
expect($formatted)->toBeString()
->and(str_starts_with($formatted, '-----BEGIN'))->toBeTrue()
->and(str_contains($formatted, 'PRIVATE KEY-----'))->toBeTrue();
});
it('can format public key', function () {
$formatted = RSA::publicKeyFormat($this->publicKeyString);
expect($formatted)->toBeString()
->and(str_starts_with($formatted, '-----BEGIN PUBLIC KEY-----'))->toBeTrue()
->and(str_contains($formatted, '-----END PUBLIC KEY-----'))->toBeTrue();
});
it('can format certificate', function () {
$certContent = 'MIICljCCAX4CCQDlE4BS663G8DANBgkqhkiG9w0BAQUFADCBjTELMAkGA1UEBhMCVVMxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFpdWdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFtcGxlLmNvbTAeFw0yNTExMTUxMjAwMDBaFw0yNjExMTUxMjAwMDBaMIGNMQswCQYDVQQGEwJVUzETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRIwEAYDVQQDDAlsb2NhbGhvc3QxIDAeBgkqhkiG9w0BCQEWEWFkbWluQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5I8+xT2+dWXJBUtZVIHZ5Xkp4FQ9bo1+W4KxgH5nPD9D+7pQy6AHZRjYADmHuQ0GAbPyayGdVPW23h9X1v0cYO36pzH8OZKV8iZw1rOBRss4I3ZchILsBfqdVDNYKCjD1IhCcS2u4nMYKqEyUJ4xVhHkKJqVwuEZ5X5ohJ04j2QIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAIyF5Y+pmAhHHW4Kv4gI8D37OZCvsFysvxj7D3BYI5qMNnK16YZcgPwPqptE0iH9miGBVZuRKaeAUN4qgQxhIlSmKyuprI3VvyQ7EGXn5FTDNJUBHaQhAomKNXX6Y+jlFE6QpW93iBwjjRYT5uTKaFznD5cBy3bFYW1xJ2R2P9mH';
$formatted = RSA::certificateFormat($certContent);
expect($formatted)->toBeString()
->and(str_starts_with($formatted, '-----BEGIN CERTIFICATE-----'))->toBeTrue()
->and(str_contains($formatted, '-----END CERTIFICATE-----'))->toBeTrue();
});
it('throws exception for invalid private key', function () {
expect(fn () => RSA::getPrivateKey('invalid private key'))->toThrow(RuntimeException::class);
});
it('throws exception for invalid public key', function () {
expect(fn () => RSA::getPublicKey('invalid public key'))->toThrow(RuntimeException::class);
});
it('can encrypt and decrypt data', function () {
$encrypted = RSA::encrypt($this->testMessage, $this->publicKey);
expect($encrypted)->toBeString()
->and($encrypted)->not->toEqual($this->testMessage);
$decrypted = RSA::decrypt($encrypted, $this->privateKey);
expect($decrypted)->toBeString()
->and($decrypted)->toEqual($this->testMessage);
});
it('can sign and verify data', function () {
$signature = RSA::sign($this->testMessage, $this->privateKey, OPENSSL_ALGO_SHA256);
expect($signature)->toBeString();
$isValid = RSA::verify($this->testMessage, $signature, $this->publicKey, OPENSSL_ALGO_SHA256);
expect($isValid)->toBeTrue();
// 验证篡改后的消息无法通过验证
$isValidTampered = RSA::verify($this->testMessage.'tampered', $signature, $this->publicKey, OPENSSL_ALGO_SHA256);
expect($isValidTampered)->toBeFalse();
});
it('throws exception on encryption failure', function () {
$invalidKey = $this->publicKey;
// 创建一个无效的密钥用于测试(这里我们模拟一个场景)
expect(fn () => RSA::encrypt($this->testMessage, $invalidKey, 999))->toThrow(RuntimeException::class, '加密失败');
})->skip();
it('throws exception on decryption failure', function () {
expect(fn () => RSA::decrypt('invalid cipher text', $this->privateKey))->toThrow(
RuntimeException::class,
'解密失败',
);
});
it('throws exception on signing failure', function () {
expect(fn () => RSA::sign($this->testMessage, $this->privateKey, 999))->toThrow(RuntimeException::class, '签名失败');
})->skip();
it('can get public key from certificate', function () {
$certContent = '-----BEGIN CERTIFICATE-----
MIICljCCAX4CCQDlE4BS663G8DANBgkqhkiG9w0BAQUFADCBjTELMAkGA1UEBhMCVVMxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFpdWdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFtcGxlLmNvbTAeFw0yNTExMTUxMjAwMDBaFw0yNjExMTUxMjAwMDBaMIGNMQswCQYDVQQGEwJVUzETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRIwEAYDVQQDDAlsb2NhbGhvc3QxIDAeBgkqhkiG9w0BCQEWEWFkbWluQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5I8+xT2+dWXJBUtZVIHZ5Xkp4FQ9bo1+W4KxgH5nPD9D+7pQy6AHZRjYADmHuQ0GAbPyayGdVPW23h9X1v0cYO36pzH8OZKV8iZw1rOBRss4I3ZchILsBfqdVDNYKCjD1IhCcS2u4nMYKqEyUJ4xVhHkKJqVwuEZ5X5ohJ04j2QIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAIyF5Y+pmAhHHW4Kv4gI8D37OZCvsFysvxj7D3BYI5qMNnK16YZcgPwPqptE0iH9miGBVZuRKaeAUN4qgQxhIlSmKyuprI3VvyQ7EGXn5FTDNJUBHaQhAomKNXX6Y+jlFE6QpW93iBwjjRYT5uTKaFznD5cBy3bFYW1xJ2R2P9mH
-----END CERTIFICATE-----';
expect(fn () => RSA::getPublicKeyFromCert($certContent))->toThrow(RuntimeException::class, '证书加载失败');
});
it('can get certificate serial number', function () {
$certContent = '-----BEGIN CERTIFICATE-----
MIICljCCAX4CCQDlE4BS663G8DANBgkqhkiG9w0BAQUFADCBjTELMAkGA1UEBhMCVVMxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFpdWdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFtcGxlLmNvbTAeFw0yNTExMTUxMjAwMDBaFw0yNjExMTUxMjAwMDBaMIGNMQswCQYDVQQGEwJVUzETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRIwEAYDVQQDDAlsb2NhbGhvc3QxIDAeBgkqhkiG9w0BCQEWEWFkbWluQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5I8+xT2+dWXJBUtZVIHZ5Xkp4FQ9bo1+W4KxgH5nPD9D+7pQy6AHZRjYADmHuQ0GAbPyayGdVPW23h9X1v0cYO36pzH8OZKV8iZw1rOBRss4I3ZchILsBfqdVDNYKCjD1IhCcS2u4nMYKqEyUJ4xVhHkKJqVwuEZ5X5ohJ04j2QIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAIyF5Y+pmAhHHW4Kv4gI8D37OZCvsFysvxj7D3BYI5qMNnK16YZcgPwPqptE0iH9miGBVZuRKaeAUN4qgQxhIlSmKyuprI3VvyQ7EGXn5FTDNJUBHaQhAomKNXX6Y+jlFE6QpW93iBwjjRYT5uTKaFznD5cBy3bFYW1xJ2R2P9mH
-----END CERTIFICATE-----';
expect(fn () => RSA::getCertSn($certContent))->toThrow(RuntimeException::class, '证书加载失败');
});
it('can get public key string from certificate', function () {
$certContent = '-----BEGIN CERTIFICATE-----
MIICljCCAX4CCQDlE4BS663G8DANBgkqhkiG9w0BAQUFADCBjTELMAkGA1UEBhMCVVMxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFpdWdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFtcGxlLmNvbTAeFw0yNTExMTUxMjAwMDBaFw0yNjExMTUxMjAwMDBaMIGNMQswCQYDVQQGEwJVUzETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRIwEAYDVQQDDAlsb2NhbGhvc3QxIDAeBgkqhkiG9w0BCQEWEWFkbWluQGV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5I8+xT2+dWXJBUtZVIHZ5Xkp4FQ9bo1+W4KxgH5nPD9D+7pQy6AHZRjYADmHuQ0GAbPyayGdVPW23h9X1v0cYO36pzH8OZKV8iZw1rOBRss4I3ZchILsBfqdVDNYKCjD1IhCcS2u4nMYKqEyUJ4xVhHkKJqVwuEZ5X5ohJ04j2QIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAIyF5Y+pmAhHHW4Kv4gI8D37OZCvsFysvxj7D3BYI5qMNnK16YZcgPwPqptE0iH9miGBVZuRKaeAUN4qgQxhIlSmKyuprI3VvyQ7EGXn5FTDNJUBHaQhAomKNXX6Y+jlFE6QpW93iBwjjRYT5uTKaFznD5cBy3bFYW1xJ2R2P9mH
-----END CERTIFICATE-----';
expect(fn () => RSA::getPublicKeyStringFromCert($certContent))->toThrow(RuntimeException::class, '证书加载失败');
});