← Назад к вопросам

Чем шифруется сертификат?

2.0 Middle🔥 71 комментариев
#Безопасность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Как шифруется сертификат

Определение

Сертификат (X.509) — это документ, который подтверждает подлинность публичного ключа и содержит информацию о владельце. Сертификат подписан Certificate Authority (CA) — доверенной организацией.

Структура сертификата

X.509 Certificate
├── Тело сертификата (To Be Signed)
│   ├── Version
│   ├── Serial Number
│   ├── Signature Algorithm
│   ├── Issuer (кто выдал)
│   ├── Subject (для кого выдан)
│   ├── Public Key
│   ├── Validity Period (срок действия)
│   └── Extensions
│
└── Подпись (создана CA приватным ключом)

Как сертификат подписывается (не шифруется!)

Важно: сертификат не шифруется, а подписывается. Это разные операции!

Процесс подписи сертификата

1. Создание сертификата (public key + metadata)
   ↓
2. Хеширование содержимого (SHA-256)
   Content Hash = SHA256(certificate_data)
   ↓
3. Шифрование хеша приватным ключом CA (RSA)
   Digital Signature = RSA_Encrypt(Content Hash, CA_Private_Key)
   ↓
4. Добавление подписи в сертификат
   ↓
5. Отправка: Сертификат + Подпись (открытый текст!)

Алгоритмы шифрования подписи

RSA (Rivest-Shamir-Adleman)

Мост распространённый алгоритм для подписи сертификатов:

Процесс подписи:
1. Hash = SHA256(certificate_data)
2. Signature = RSA_Encrypt(Hash, CA_Private_Key)  // 2048-4096 бит

Процесс проверки подписи:
1. Signature = RSA_Decrypt(Signature, CA_Public_Key)
2. Hash = SHA256(certificate_data)
3. Если Signature == Hash → подпись валидна

Длины ключей:

  • 2048 бит — минимум (устаревает)
  • 4096 бит — текущий стандарт
  • 8192 бит — для высокой безопасности
// Проверка подписи RSA сертификата в Java
import java.security.*;
import java.security.cert.X509Certificate;

public class CertificateValidator {
    
    public static boolean validateCertificateSignature(
            X509Certificate cert,
            PublicKey caPublicKey) throws Exception {
        
        try {
            // Verify использует публичный ключ CA
            cert.verify(caPublicKey);
            System.out.println("Certificate signature is valid!");
            return true;
        } catch (SignatureException e) {
            System.out.println("Certificate signature is invalid!");
            return false;
        }
    }
}

ECDSA (Elliptic Curve Digital Signature Algorithm)

Современный алгоритм, более эффективный чем RSA:

Процесс подписи:
1. Hash = SHA256(certificate_data)
2. Signature = ECDSA_Sign(Hash, CA_Private_Key)  // 256-521 бит
   (производит пару (r, s))

Процесс проверки подписи:
1. (r, s) = Signature
2. Hash = SHA256(certificate_data)
3. Если ECDSA_Verify(Hash, r, s, CA_Public_Key) → валидна

Преимущества ECDSA:

  • Меньше размер ключей (256 бит = 2048 бит RSA)
  • Быстрее вычисления
  • Подходит для мобильных приложений
// Создание ECDSA подписи
import java.security.*;

KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
keyGen.initialize(256);  // NIST P-256
KeyPair keyPair = keyGen.generateKeyPair();

// Подпись
Signature sig = Signature.getInstance("SHA256withECDSA");
sig.initSign(keyPair.getPrivate());
sig.update(certificate_data);
byte[] signature = sig.sign();

// Проверка подписи
Signature verifySignature = Signature.getInstance("SHA256withECDSA");
verifySignature.initVerify(keyPair.getPublic());
verifySignature.update(certificate_data);
boolean isValid = verifySignature.verify(signature);

SHA-256 (Хеширование)

Сертификат хешируется перед подписью:

import java.security.MessageDigest;

public class HashExample {
    
    public static String hashCertificate(byte[] certificateData) 
            throws Exception {
        
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hash = digest.digest(certificateData);
        
        // Преобразование в hex
        StringBuilder hexString = new StringBuilder();
        for (byte b : hash) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) hexString.append('0');
            hexString.append(hex);
        }
        
        return hexString.toString();
    }
}

// Output (для Google сертификата):
// 587c45eaaac0ec9ed8fc09b25ebb4b87d894eef6b0b9b8ea08fb8d00de2d87aa

Цепь доверия (Certificate Chain)

Когда браузер получает сертификат:

1. Получает сертификат сервера (например, google.com)
   - Выдан: DigiCert
   - Публичный ключ: xxxxxxxx
   - Подпись: yyyyyyyy (подписано приватным ключом DigiCert)
   
2. Получает сертификат выдающего центра (DigiCert)
   - Выдан: GlobalSign (root CA)
   - Подпись: zzzzzzzz (подписано GlobalSign)
   
3. Получает root сертификат (GlobalSign)
   - Самоподписанный (выдан сам себе)
   - Уже есть в браузере в trusted roots

4. Проверяет цепь:
   google.com сертификат ← DigiCert публичный ключ
   DigiCert сертификат ← GlobalSign публичный ключ
   GlobalSign сертификат ← trusted (встроен в браузер)
   
   Если все подписи верны → доверять сайту

Алгоритмы до подписи

Дополнительные алгоритмы для подписи:

1. SHA-1 (устаревший, опасный)
   - Длина: 160 бит
   - Уязвимости известны
   - Больше не используется для сертификатов

2. SHA-256 (текущий стандарт)
   - Длина: 256 бит
   - Безопасен
   - Используется: RSA, ECDSA

3. SHA-384, SHA-512
   - Еще надежнее
   - Для критичных систем

Просмотр алгоритма сертификата

Через OpenSSL

# Просмотр сертификата
openssl x509 -in certificate.pem -text -noout

# Output:
# Signature Algorithm: sha256WithRSAEncryption
# Public-Key: (2048 bit)
# Issuer: C = US, O = Google Trust Services, CN = Google Internet Authority

Через Java

import java.security.cert.X509Certificate;
import java.io.FileInputStream;
import java.security.KeyStore;

public class CertificateInfo {
    
    public static void printCertificateInfo(String certPath) 
            throws Exception {
        
        FileInputStream fis = new FileInputStream(certPath);
        java.security.cert.CertificateFactory cf = 
            java.security.cert.CertificateFactory.getInstance("X.509");
        
        X509Certificate cert = 
            (X509Certificate) cf.generateCertificate(fis);
        
        System.out.println("Subject: " + cert.getSubjectDN());
        System.out.println("Issuer: " + cert.getIssuerDN());
        System.out.println("Algorithm: " + cert.getSigAlgName());
        // Output: Algorithm: SHA256withRSA
        
        System.out.println("Public Key Algorithm: " + 
                          cert.getPublicKey().getAlgorithm());
        // Output: RSA
        
        System.out.println("Valid from: " + cert.getNotBefore());
        System.out.println("Valid until: " + cert.getNotAfter());
        
        fis.close();
    }
}

HTTPS процесс

1. Клиент подключается к серверу (порт 443)
   Client                      Server
   |                              |
   |---- ClientHello ----------->
   |                              |
   |<--- ServerHello + Cert ------| (Сервер отправляет сертификат)
   |                              |
   |---- Клиент проверяет --------| (Проверяет подпись CA)
   |     cert (RSA с SHA-256)     |
   |                              |
   |---- Certificate OK --------->| (Если подпись верна)
   |                              |
   |<--- TLS established ---------| (Шифрованное соединение)

Best Practices

  1. Используй SHA-256 или выше:

    // Хорошо
    Signature sig = Signature.getInstance("SHA256withRSA");
    
    // Плохо (устаревший)
    Signature sig = Signature.getInstance("SHA1withRSA");
    
  2. Используй ключи 2048+ бит:

    # Проверить размер ключа
    openssl x509 -in cert.pem -text -noout | grep "Public-Key"
    
  3. Проверяй цепь доверия:

    cert.verify(caPublicKey);  // Проверяет подпись
    
  4. Используй ECDSA для новых приложений:

    Signature sig = Signature.getInstance("SHA256withECDSA");
    

Вывод

Сертификат не шифруется, а подписывается приватным ключом Certificate Authority. Процесс:

  1. Содержимое сертификата хешируется (SHA-256)
  2. Хеш шифруется приватным ключом CA (RSA-2048/4096 или ECDSA)
  3. Результат (подпись) добавляется в сертификат
  4. При проверке браузер расшифровывает подпись публичным ключом CA и сравнивает с хешем

Текущие стандарты: SHA-256 с RSA-2048+ или ECDSA-256.

Чем шифруется сертификат? | PrepBro