Appearance
Digital Certificates
We know that hash algorithms ensure data has not been tampered with, asymmetric encryption algorithms can encrypt and decrypt data, and signature algorithms ensure data integrity and non-repudiation. Combining these algorithms and establishing a comprehensive standard forms what is known as a digital certificate.
What is a Digital Certificate?
A digital certificate integrates multiple cryptographic algorithms to provide functionalities such as data encryption and decryption, identity authentication, and signing. It serves as a security standard that encapsulates these various cryptographic operations.
Digital certificates help prevent man-in-the-middle (MITM) attacks by employing a chain of signature authentication. This chain starts with a root certificate (Root CA) that signs subordinate certificates, creating a hierarchical trust model. The root CA certificate is embedded within the operating system, ensuring that any digital certificate certified by the CA can be verified for authenticity, thereby preventing the forging of certificates.
Application of Digital Certificates in HTTPS
A common application of digital certificates is in the HTTPS protocol used when browsing the internet. Browsers automatically validate the validity of certificates:
Creating a Digital Certificate
To use digital certificates, you first need to create one. Under normal circumstances, a legitimate digital certificate must be signed by a Certificate Authority (CA), which involves domain authentication and certain fees. For development purposes, you can use a self-signed certificate. Such certificates are suitable for development and debugging but cannot be used for public services because clients do not recognize certificates that have not been signed by a CA.
Note: Tencent Cloud offers free SSL certificates valid for one year, and Let's Encrypt provides free SSL certificates valid for 90 days.
In Java programs, digital certificates are stored in a Java-specific KeyStore file. The JDK provides a series of commands to create and manage KeyStores. Below is a command to create a KeyStore and set the password to 123456
:
bash
keytool -storepass 123456 -genkeypair -keyalg RSA -keysize 1024 -sigalg SHA1withRSA -validity 3650 -alias mycert -keystore my.keystore -dname "CN=www.sample.com, OU=sample, O=sample, L=BJ, ST=BJ, C=CN"
Key Parameters:
keyalg
: Specifies the RSA encryption algorithm.sigalg
: Specifies the SHA1withRSA signature algorithm.validity
: Sets the certificate validity period to 3650 days.alias
: Defines the name used to reference the certificate within the program.dname
: Most importantly,CN=www.sample.com
specifies the Common Name. If the certificate is used for HTTPS, this name must exactly match the domain name.
Executing the above command will create a my.keystore
file in the current directory, storing a newly created private key and a certificate with the alias mycert
.
Using Digital Certificates for Encryption and Signing
With the certificate stored in the KeyStore, you can perform encryption, decryption, signing, and verification using digital certificates:
java
import java.io.InputStream;
import java.security.*;
import java.security.cert.*;
import javax.crypto.Cipher;
import java.util.HexFormat;
public class Main {
public static void main(String[] args) throws Exception {
byte[] message = "Hello, use X.509 cert!".getBytes("UTF-8");
// Load KeyStore:
KeyStore ks = loadKeyStore("/my.keystore", "123456");
// Retrieve Private Key:
PrivateKey privateKey = (PrivateKey) ks.getKey("mycert", "123456".toCharArray());
// Retrieve Certificate:
X509Certificate certificate = (X509Certificate) ks.getCertificate("mycert");
// Encrypt:
byte[] encrypted = encrypt(certificate, message);
System.out.println("encrypted: " + HexFormat.of().formatHex(encrypted));
// Decrypt:
byte[] decrypted = decrypt(privateKey, encrypted);
System.out.println("decrypted: " + new String(decrypted, "UTF-8"));
// Sign:
byte[] sign = sign(privateKey, certificate, message);
System.out.println("signature: " + HexFormat.of().formatHex(sign));
// Verify Signature:
boolean verified = verify(certificate, message, sign);
System.out.println("verify: " + verified);
}
static KeyStore loadKeyStore(String keyStoreFile, String password) {
try (InputStream input = Main.class.getResourceAsStream(keyStoreFile)) {
if (input == null) {
throw new RuntimeException("file not found in classpath: " + keyStoreFile);
}
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(input, password.toCharArray());
return ks;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static byte[] encrypt(X509Certificate certificate, byte[] message) throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance(certificate.getPublicKey().getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, certificate.getPublicKey());
return cipher.doFinal(message);
}
static byte[] decrypt(PrivateKey privateKey, byte[] data) throws GeneralSecurityException {
Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
static byte[] sign(PrivateKey privateKey, X509Certificate certificate, byte[] message)
throws GeneralSecurityException {
Signature signature = Signature.getInstance(certificate.getSigAlgName());
signature.initSign(privateKey);
signature.update(message);
return signature.sign();
}
static boolean verify(X509Certificate certificate, byte[] message, byte[] sig) throws GeneralSecurityException {
Signature signature = Signature.getInstance(certificate.getSigAlgName());
signature.initVerify(certificate);
signature.update(message);
return signature.verify(sig);
}
}
In the above code:
- KeyStore Loading: The KeyStore is loaded from the specified file with the given password.
- Private Key Retrieval: The private key is retrieved from the KeyStore using the alias
mycert
and the password. - Certificate Retrieval: The public key is obtained from the certificate stored in the KeyStore.
- Encryption and Decryption: The public key encrypts the message, and the private key decrypts the ciphertext.
- Signing and Verification:
- The private key signs the message.
- The public key verifies the signature against the message.
Note: In the code, X509Certificate
only contains the public key, so retrieving the certificate does not require a password. Only accessing the private key necessitates providing the password.
When deploying to a web server, such as Nginx, you need to export the private key in Private Key format and the certificate in X509Certificate format.
HTTPS Protocol Example
Using the HTTPS protocol as an example, the steps for establishing a secure connection between a browser and a server are as follows:
- Request Initiation: The browser sends a request to the server.
- Certificate Transmission: The server sends its digital certificate to the browser.
- Certificate Validation: The browser uses the Root CA embedded in the operating system to verify the server’s certificate. If valid, the browser encrypts a random AES key using the server’s public key and sends it to the server.
- AES Key Decryption: The server decrypts the AES key using its private key.
- Secure Communication: Both the browser and the server use the shared AES key for subsequent communications, utilizing the faster symmetric AES encryption instead of the slower RSA asymmetric encryption.
This process describes a common one-way authentication scenario. If the server also needs to authenticate the client, the client must provide its own certificate for verification, which is typical in scenarios like online banking.
Important: Digital certificates store public keys, certificate chains, and algorithm information. The private key must be strictly confidential. If the private key corresponding to a digital certificate is compromised, it poses a severe security threat. For instance, the digital certificate service provider DigiNotar experienced a private key leak, leading to the company's bankruptcy due to the trust issues arising from all certificates signed by the compromised CA becoming unreliable.
Exercise
Use digital certificates to implement message encryption.
Summary
- Digital Certificates: Integrate multiple cryptographic algorithms to provide data encryption, identity authentication, signing, and other security functionalities.
- Chain of Trust: Employ a chain of signature authentication managed through root certificates (Root CA) embedded in operating systems, ensuring that all CA-certified certificates can be verified for authenticity.
- Public and Private Keys: Digital certificates store public keys securely for sharing, while private keys must be kept strictly confidential.
- KeyStore Management: Java KeyStores store certificates and private keys, allowing for encryption, decryption, signing, and verification operations within Java applications.
- HTTPS Protocol Usage: Demonstrates how browsers and servers use digital certificates to establish secure communications by exchanging and verifying certificates, and subsequently using symmetric encryption for data transmission.
- Security Implications: Emphasizes the critical importance of keeping private keys secure to prevent severe security breaches and loss of trust in the certificate authority.