Essential Skills for API Integration: Detailed Explanation of Common Encryption and Signature Algorithms

Before reading this chapter, please first understand the theory of encoding and decoding in computer basics and an introduction to OpenSSL.What is the relationship between binary, hexadecimal, bytes, and strings?

HTTPS, certificates, data encryption… How many of these OpenSSL skills have you used?

Below is the main content

Encryption Algorithms

In API integration, commonly used encryption and signature algorithms include symmetric encryption and asymmetric encryption.

Symmetric encryption algorithms include AES and SM4, where both parties use the same key. Symmetric encryption can be used in scenarios such as data encryption and desensitization, as it has high encryption and decryption efficiency.

Asymmetric encryption algorithms include RSA2 and SM2, where each party has a pair of public and private keys. Before communication, they exchange public keys, and the private key should be kept secret. The general process of asymmetric encryption is: sign the plaintext request with your private key, then encrypt both the plaintext and the signature with the other party’s public key; upon receiving the request, the other party first decrypts it with their private key to obtain the plaintext and signature, and then verifies the signature using your public key.

The original format of public and private keys is binary data stored in certificate files. However, for ease of reading and transmission, keys are often displayed in hexadecimal or Base64 encoding formats, so the same encryption algorithm may have different key formats.

For example: The Base64 format and hexadecimal format of SM2 are as follows:

Hexadecimal format: Public Key: 04A5C65A40B977D4F909833722EF950374D0B8791B9E7B9F5712D573F964706879E4AFD1DA142DBDD5B305824EDFC02B73CEB6F50B71DB2089E214C58230A0875F Private Key: 00FD954A8820A25A406396DBEAC9CEE9AD7F1FEA29D22EEBA9682647D482FDA32E
Base64 format: Public Key: BEViYfuleJ4ZCczcVVx6UY38IgGi0C/++EW72YMKff3uSNownfWnzy5AFLIuGce1ig3zjMITJt1xvPXTYax+NdA= Private Key: AJw7Dn/tBoNhtyGmmXc8S0DxWBXKIWe5iZD4dMZ1GebD

Usage

In practical use, keys can be represented in two forms: string keys and certificate files.

String Keys

String keys are more often used for simple encryption and signing tasks. When strong authentication or trust mechanisms are not required, a string key can be used directly for symmetric encryption or simple digital signature verification.

In asymmetric encryption, the private key is stored locally, and the public key is sent to the other party. If the string public key is sent directly to the other party, and the string data is tampered with by a man-in-the-middle, then the encryption and signature will be untrustworthy. To ensure a higher level of communication security, it is essential to guarantee that the public key is legitimate and untampered, which is why public key digital certificates are introduced.

Digital Certificates

The main purpose of digital certificates is to solve the problem of verifying the legitimacy of public keys in asymmetric encryption. Their main advantage is that they provide higher security and credibility, especially in scenarios involving public key encryption and identity verification. Certificates not only contain the keys but also include issuance information and verification chains, preventing man-in-the-middle attacks and ensuring the authenticity of communication.

The issuance logic of public key certificates is to sign the public key, domain name, organization name, and other information with the private key of the CA root certificate (ignoring intermediate certificates). How to verify the legitimacy of the public key? You only need to use the public key of the root certificate to verify whether the signature of the public key certificate is valid.

Therefore, a public key certificate contains the following contents:

  • Certificate Structure Digital certificates (such as X.509 format) are files composed of public keys and the identity information of the signer, usually issued by a trusted third-party Certificate Authority (CA).
  • The certificate includes the signer’s public key, certificate validity period, issuer information, and other contents.
  • The certificate itself is signed by the trusted Certificate Authority (CA) with its private key, ensuring the authenticity of the certificate.
  • Identity Verification The certificate not only contains the public key but also binds the identity information of the signer. The signer’s identity is certified by the Certificate Authority (CA), and the recipient can verify the validity of the certificate through the CA’s public key, thereby verifying the identity of the signer.
  • Trust Chain The certificate is issued by the Certificate Authority (CA), thus following a trust chain mechanism. Root Certificate -> Intermediate Certificate -> User Certificate, establishing a trusted verification system.
  • Management Method When using certificate signatures, it is necessary to protect the private key and ensure the validity and credibility of the certificate. Certificates may expire or be revoked, requiring regular updates and checks.
  • Signature Verification The recipient not only verifies whether the signature is correct but also checks whether the certificate is valid, whether it is trusted, and verifies the identity of the signer through the certificate chain.

How Merchants Apply for Digital Certificates

Apply for a public key certificate through a Certificate Signing Request (CSR), which is a standard step in the digital certificate generation process.

Yes, generating a Certificate Signing Request (CSR) file and uploading it to the other party’s platform for issuance is a standard step in the digital certificate generation process. The core purpose of this process is to ensure the security, legality, and validity of the certificate. Here is a detailed explanation:

CSR file is a file that contains information about the applicant and the public key. When generating a CSR, it typically includes the following content:

  • Public Key used for encryption and signature verification.
  • Organization Information such as company name, organizational unit, country, region, etc.
  • Subject Name which is the entity information applying for the certificate (such as domain name, personal name, etc.).
  • Signature Algorithm specifies the algorithm used to generate the CSR, such as RSA or ECC.

The CSR file is a key part of the certificate application process. Its role is that the process of generating the CSR is usually done after generating the private key and public key pair locally. The private key is always kept locally and is not disclosed to the Certificate Authority (CA). Only the public key and identity information are submitted to the CA, ensuring the private key remains secure. When generating the CSR, the applicant’s private key is used to sign the CSR file. This signature ensures the integrity and authenticity of the CSR file, meaning that only users with the correct private key can generate a valid CSR. The Certificate Authority (CA) uses the public key and signature in the submitted CSR file to verify the legitimacy of the public key and signs the certificate with its private key, issuing the public key digital certificate.

Applying for Application Public Key from Alipay

First, generate the public key and private key locally, then generate the CSR certificate signing request file, upload it to the Alipay backend, click to generate the public key certificate file and download it.

Here are three public key certificates:

1. Application public key certificate, issued using the corresponding private key from the CSR certificate signing request file;

2. Alipay public key certificate, issued using the private key of the Alipay root certificate;

3. Alipay root certificate, which is used to verify the legitimacy of the Alipay public key certificate;

Three Usage Scenarios of Certificates

1. Signing and encrypting HTTP request messages, mutual authentication;

This method is the most common, using certificates to sign message data, commonly seen in various API integrations.

2. Establishing secure communication between HTTP SSL/TLS clients and servers, one-way authentication;

One-way authentication means that only the client verifies the identity of the server, that is, during the SSL/TLS handshake, the client verifies the server’s certificate (usually issued by a CA). The server does not verify the client’s identity. For example, when accessing Baidu, the client uses a public key from a trusted Certificate Authority (CA) to verify the validity of the server’s certificate (i.e., whether it is issued by a trusted CA, whether it is expired, whether it has been tampered with). Most HTTPS websites use one-way authentication.

3. Establishing secure communication between HTTP SSL/TLS clients and servers, mutual authentication;

Mutual authentication (also known as two-way SSL or two-way TLS) means that both the client and server verify each other’s identities. In this mode, in addition to the server providing a certificate to the client, the client also needs to provide its own certificate for the server to verify. For example, in banking applications, internal enterprise services, payment systems, etc., it ensures that only legitimate clients and servers can establish connections, and this method has the highest level of security for API integration.

Below is a demonstration of the client using the OpenSSL tool for the RSA2 algorithm public key self-signing process:

## 1. Generate a private key, length 2048 bits, algorithm RSA
openssl genrsa -out own-private.key 2048

## 2. Generate a public key certificate (with the private key, the public key can be derived), 1825 is the validity period/days
openssl req -x509 -new -key own-private.key -out own-certificate.crt -days 1825

## 3. Package the certificate and private key into a PKCS#12 file (this), need to set a password and confirm it
openssl pkcs12 -export -in own-certificate.crt -inkey own-private.key -out own.p12

The self-signing process omits the step of generating a CSR to apply for a CA certificate, directly generating the certificate locally, using your private key to prove that your public key is legitimate. This cannot be used on the internet, only for internal use. The PKCS#12 file extension is “.p12 ” or “.pfx”, which contains the user’s public key, private key, personal information, etc. Therefore, when using mutual identity verification, you only need to import the p12 file directly.

In the commands above, the public key is not generated because it can be derived from the private key, so it is not explicitly created. Since the certificate is a wrapper for the public key, it contains not only the public key but also the certificate holder’s information, the certificate’s validity period, signature algorithm, and other contents. Typically, we see the public key in SSL/TLS certificates, which are used together with the private key. You can extract the public key from the private key using the following command:

# Export public key
openssl rsa -in own-private.key -pubout -out own-public.key

Here is a demonstration of how to import the key pair and initiate an HTTP request:

1. Initialize RestTemplate

import lombok.extern.slf4j.Slf4j;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import javax.net.ssl.*;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
@Slf4j
@Configuration
public class SSLContextConfig {
    @Bean(name = "restTemplate")
    public RestTemplate restTemplate() {
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
        // The default maximum number of connections in the pool is 100
        cm.setMaxTotal(100);
        // The maximum number of connections per host
        cm.setDefaultMaxPerRoute(20);
        RestTemplate restTemplate = null;
        try {
            HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
            // Client certificate type
            KeyStore clientStore = KeyStore.getInstance("PKCS12");
            // Load client certificate, i.e., your private key and public key certificate
            InputStream keyStream = new FileInputStream("/User/own.p12");
            // Password, here you need to enter the p12 password
            String pwd = "own";
            clientStore.load(keyStream, pwd.toCharArray());
            // Create an instance of the key management factory
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            // Initialize the client key store
            keyManagerFactory.init(clientStore, pwd.toCharArray());
            KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
            // Create an instance of the trust store management factory
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            trustStore.load(null, null);
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            InputStream certStream = new FileInputStream("/User/other party's public key.crt");
            trustStore.setCertificateEntry("server", cf.generateCertificate(certStream));
            // Initialize the trust store
            trustManagerFactory.init(trustStore);
            TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
            // Establish TLS connection
            SSLContext sslContext = SSLContext.getInstance("TLS");
            // Initialize SSLContext
            sslContext.init(keyManagers, trustManagers, new SecureRandom());
            // INSTANCE ignores domain name checks
            SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
            CloseableHttpClient httpclient = HttpClients
                    .custom()
                    .setSSLSocketFactory(sslConnectionSocketFactory)
                    .setSSLHostnameVerifier(new NoopHostnameVerifier())
                    .build();
            requestFactory.setHttpClient(httpclient);
            requestFactory.setConnectTimeout(5000);
            requestFactory.setReadTimeout(65000);
            requestFactory.setConnectionRequestTimeout(50000);
            restTemplate = new RestTemplate(requestFactory);
        } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException | CertificateException | UnrecoverableKeyException | IOException e) {
            log.warn("Certificate initialization exception", e);
            restTemplate = new RestTemplate();
        }
        return restTemplate;
    }
}

2. Send a POST request

public static void main(String[] args) {
    // Inject restTemplate
    RestTemplate restTemplate = new RestTemplate();
    String reqUrl = "Request URL";
    // Request body
    Map<String, Object> param = new HashMap<>(2);
    param.put("param","value");
    // Request header
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    // Send POST request
    HttpEntity<String> requestEntity = new HttpEntity<>(JSONObject.toJSONString(param), headers);
    ResponseEntity<String> response = restTemplate.postForEntity(reqUrl, requestEntity, String.class);
    // Get status code and response body
    HttpStatus statusCode = response.getStatusCode();
    String body = response.getBody();
}

Nginx Server Deployment requires pem files and key files, how to generate them?

When configuring SSL/TLS for Nginx or other web servers, PEM format certificate files (including certificates and private keys) are indeed used. In this case, <span>.p12</span> files are not the directly used format, but they can be converted to obtain PEM format certificates and private keys.PEM (Privacy-Enhanced Mail) format is a text format based on Base64 encoding, commonly used for storing certificates and private keys. PEM files are usually identified by headers and footers such as <span>-----BEGIN CERTIFICATE-----</span> or <span>-----BEGIN PRIVATE KEY-----</span>.

Typically, Nginx or other web servers use PEM format certificate files (including certificates and private keys) when configuring SSL/TLS. In this case, <span>.p12</span> files are not the directly used format, but they can be converted to obtain PEM format certificates and private keys. Below is how to understand this situation and how to perform the conversion.

Use OpenSSL to extract certificates and private keys from <span>.p12</span> files and convert them to the PEM format required by Nginx.

# Extract client certificate (i.e., public key certificate), do not extract private key, password own
openssl pkcs12 -in own.p12 -clcerts -nokeys -out certificate.crt

# Extract private key from p12 file, this command requires entering the p12 file password, then set the private key password to encrypt the private key.
openssl pkcs12 -in own.p12 -nocerts -out private.key

# If you do not want a password for the generated encrypted private key, you can convert it to a passwordless key again
openssl rsa -in private.key -out private_no_password.key

Nginx configuration example:

server {
    listen 443 ssl;
    server_name yourdomain.com;

    ssl_certificate /path/to/certificate.crt;  # Certificate
    ssl_certificate_key /path/to/private.key;  # Private Key

    # Optional: If you need an intermediate certificate chain, you can set ssl_certificate_chain_file
    ssl_trusted_certificate /path/to/chain.pem;
}

ps: The ssl_certificate file may have the extension pem, you just need to change certificate.crt to certificate.pem, both can be recognized.

Code Examples

Here are code demonstrations of commonly used encryption methods

Asymmetric Encryption

1. SM2 Algorithm
<dependency>  <groupId>org.bouncycastle</groupId>  <artifactId>bcprov-jdk15on</artifactId>  <version>1.70</version> <!-- You can choose the latest version --></dependency><dependency>  <groupId>org.bouncycastle</groupId>  <artifactId>bcpkix-jdk15on</artifactId>  <version>1.70</version> <!-- You can choose the latest version --></dependency>
Base64 Format
    /**     * Public key encryption,     *     * @param plainText     * @param publicKey     * @return     */    public static String sm2Encrypt(String plainText, String publicKey) {        SM2 sm2 = new SM2(null, publicKey);        return sm2.encryptBase64(plainText, KeyType.PublicKey);    }    /**     * Private key decryption     *     * @param cipherText     * @param privateKey     * @return     */    public static String sm2Decrypt(String cipherText, String privateKey) {        SM2 sm2 = new SM2(privateKey, null);        return sm2.decryptStr(cipherText, KeyType.PrivateKey);    }    // Generate key pair    public static void main(String[] args) {        String originalText = "Hello Wolrd";        KeyPair pair = SecureUtil.generateKeyPair("SM2");        byte[] privateKey = pair.getPrivate().getEncoded();        byte[] publicKey = pair.getPublic().getEncoded();        // Public key        String privateStringKey = Base64.getEncoder().encodeToString(privateKey);        // Private key        String publicStringKey = Base64.getEncoder().encodeToString(publicKey);        System.out.println("Generated public key:" + publicStringKey);        System.out.println("Generated private key:" + privateStringKey);        String encryptString = sm2Encrypt(originalText, publicStringKey);        System.out.println("Encrypted string:" + encryptString);        String decryptString = sm2Decrypt(encryptString, privateStringKey);        System.out.println("Decrypted string:" + decryptString);    }
Hexadecimal Format
import cn.hutool.core.util.HexUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.*;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
@Slf4j
public class Sm2Util {
    /**     * Elliptic curve ECParameters ASN.1 structure     */    private static final X9ECParameters X9EC_PARAMETERS = GMNamedCurves.getByName("sm2p256v1");    public static final ECDomainParameters EC_DOMAIN_PARAMETER = new ECDomainParameters(X9EC_PARAMETERS.getCurve(), X9EC_PARAMETERS.getG(), X9EC_PARAMETERS.getN());    public static void generateKey() {        // Generate key pair        ECDomainParameters domainParameters33 = new ECDomainParameters(X9EC_PARAMETERS.getCurve(), X9EC_PARAMETERS.getG(), X9EC_PARAMETERS.getN());        ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();        try {            String algorithm = "SHA1PRNG";            keyPairGenerator.init(new ECKeyGenerationParameters(domainParameters33, SecureRandom.getInstance(algorithm)));        } catch (NoSuchAlgorithmException e) {            log.error(e.getMessage(), e);        }        AsymmetricCipherKeyPair asymmetricCipherKeyPair = keyPairGenerator.generateKeyPair();        // Private key, hexadecimal format        BigInteger privateKey = ((ECPrivateKeyParameters) asymmetricCipherKeyPair.getPrivate()).getD();        String privateKeyHex = privateKey.toString(16);        log.info("privateKeyHex:{}", privateKeyHex);        // Public key, hexadecimal format        ECPoint ecPoint = ((ECPublicKeyParameters) asymmetricCipherKeyPair.getPublic()).getQ();        String publicKeyHex = Hex.toHexString(ecPoint.getEncoded(false));        log.info("publicKeyHex:{}", publicKeyHex);    }    /**     * ec Public key byteArray to ECPublicKeyParameters     *     * @param ecPubKeyArray ec public key byte array     * @return ECPublicKeyParameters     */    public static ECPublicKeyParameters ecPublicKeyByteArrayToEcPublicKeyParameters(byte[] ecPubKeyArray) {        ECPoint ecPoint = X9EC_PARAMETERS.getCurve().decodePoint(ecPubKeyArray);        return new ECPublicKeyParameters(ecPoint, EC_DOMAIN_PARAMETER);    }    /**     * ec Private key byteArray to ECPrivateKeyParameters     *     * @param ecPrivateKey ec private key byte array     * @return ECPrivateKeyParameters     */    public static ECPrivateKeyParameters ecPrivateByteArrayToEcPrivateKeyParameters(byte[] ecPrivateKey) {        return new ECPrivateKeyParameters(new BigInteger(1, ecPrivateKey), EC_DOMAIN_PARAMETER);    }    /**     * @param mode             Specifies the ciphertext structure, the old standard is C1C2C3, the new ["SM2 Cryptographic Algorithm Usage Specification" GM/T 0009-2012] standard is C1C3C2     * @param pubKeyParameters Public key     * @param srcData          Original text     * @return Depending on the mode, the output ciphertext C1C2C3 arrangement order is different. C1 is 65 bytes, the first byte is the compression identifier, fixed at 0x04, followed by 64 bytes for xy components, each 32 bytes. C3 is 32 bytes. C2 length is consistent with the original text.     */    public static byte[] encrypt(SM2Engine.Mode mode, ECPublicKeyParameters pubKeyParameters, byte[] srcData)            throws InvalidCipherTextException {        SM2Engine engine = new SM2Engine(mode);        ParametersWithRandom pwr = new ParametersWithRandom(pubKeyParameters, new SecureRandom());        engine.init(true, pwr);        return engine.processBlock(srcData, 0, srcData.length);    }    /**     * @param mode             Specifies the ciphertext structure, the old standard is C1C2C3, the new ["SM2 Cryptographic Algorithm Usage Specification" GM/T 0009-2012] standard is C1C3C2     * @param priKeyParameters Private key     * @param sm2Cipher        Depending on the mode, the input ciphertext C1C2C3 arrangement order is different. C1 is 65 bytes, the first byte is the compression identifier, fixed at 0x04, followed by 64 bytes for xy components, each 32 bytes. C3 is 32 bytes. C2 length is consistent with the original text.     * @return Original text. SM2 decryption returns the data, which must be the original text, because SM2 has built-in verification. If the ciphertext is tampered with or the keys do not match, an exception will be thrown directly.     */    public static byte[] decrypt(SM2Engine.Mode mode, ECPrivateKeyParameters priKeyParameters, byte[] sm2Cipher)            throws InvalidCipherTextException {        SM2Engine engine = new SM2Engine(mode);        engine.init(false, priKeyParameters);        return engine.processBlock(sm2Cipher, 0, sm2Cipher.length);    }    /**     * Convert hexadecimal public key to base64 encrypted data, removed 04     *     * @param publicKeyHex 16 hexadecimal public key     * @param srcData      Data to be encrypted     * @return base64 encrypted data     */    @SneakyThrows    public static String encryptByHexPublicKeyToBase64(String publicKeyHex, String srcData) {        ECPublicKeyParameters ecPublicKeyParameters = ecPublicKeyByteArrayToEcPublicKeyParameters(HexUtil.decodeHex(publicKeyHex));        byte[] encrypt = encrypt(SM2Engine.Mode.C1C3C2, ecPublicKeyParameters, srcData.getBytes(StandardCharsets.UTF_8));        byte[] newEncrypt = new byte[encrypt.length - 1];        System.arraycopy(encrypt, 1, newEncrypt, 0, encrypt.length - 1);        return Base64.toBase64String(newEncrypt);    }    /**     * Decrypt base64 data using hexadecimal private key, complete 04     *     * @param privateKeyHex 16 hexadecimal private key     * @param base64SrcData Data to be decrypted     * @return Decrypted data     */    @SneakyThrows    public static String decryptBase64ByHexPrivateKeyToStr(String privateKeyHex, String base64SrcData) {        byte[] decode = Base64.decode(base64SrcData);        byte[] cipherDataByte = new byte[decode.length + 1];        cipherDataByte[0] = 4;        System.arraycopy(decode, 0, cipherDataByte, 1, decode.length);        ECPrivateKeyParameters ecPrivateKeyParameters = ecPrivateByteArrayToEcPrivateKeyParameters(HexUtil.decodeHex(privateKeyHex));        byte[] decrypt = decrypt(SM2Engine.Mode.C1C3C2, ecPrivateKeyParameters, cipherDataByte);        return new String(decrypt, StandardCharsets.UTF_8);    }    public static void main(String[] args) {        //todo        String privateKey = "";        String publicKey = "";        String srcData = "hello world";        String encrypt = encryptByHexPublicKeyToBase64(publicKey, srcData);        log.info(encrypt);        String decrypt = decryptBase64ByHexPrivateKeyToStr(privateKey, encrypt);        log.info(decrypt);    }}
2. RSA Algorithm
import java.security.*;
import java.util.Base64;
public class AsymmetricEncryptionUtils {
    // RSA Encryption    public static String encryptRSA(String content, PublicKey publicKey) throws Exception {        Cipher cipher = Cipher.getInstance("RSA");        cipher.init(Cipher.ENCRYPT_MODE, publicKey);        byte[] encrypted = cipher.doFinal(content.getBytes());        return Base64.getEncoder().encodeToString(encrypted);    }
    // RSA Decryption    public static String decryptRSA(String encryptedContent, PrivateKey privateKey) throws Exception {        Cipher cipher = Cipher.getInstance("RSA");        cipher.init(Cipher.DECRYPT_MODE, privateKey);        byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encryptedContent));        return new String(decrypted);    }
    // Generate RSA key pair    public static KeyPair generateRSAKeyPair() throws NoSuchAlgorithmException {        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");        keyPairGenerator.initialize(2048);        return keyPairGenerator.generateKeyPair();    }
}

Symmetric Encryption

1. AES and DES
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class SymmetricEncryptionUtils {
    // AES Encryption    public static String encryptAES(String content, String key) throws Exception {        Cipher cipher = Cipher.getInstance("AES");        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES");        cipher.init(Cipher.ENCRYPT_MODE, secretKey);        byte[] encrypted = cipher.doFinal(content.getBytes());        return Base64.getEncoder().encodeToString(encrypted);    }
    // AES Decryption    public static String decryptAES(String encryptedContent, String key) throws Exception {        Cipher cipher = Cipher.getInstance("AES");        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES");        cipher.init(Cipher.DECRYPT_MODE, secretKey);        byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encryptedContent));        return new String(decrypted);    }
    // DES Encryption    public static String encryptDES(String content, String key) throws Exception {        Cipher cipher = Cipher.getInstance("DES");        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "DES");        cipher.init(Cipher.ENCRYPT_MODE, secretKey);        byte[] encrypted = cipher.doFinal(content.getBytes());        return Base64.getEncoder().encodeToString(encrypted);    }
    // DES Decryption    public static String decryptDES(String encryptedContent, String key) throws Exception {        Cipher cipher = Cipher.getInstance("DES");        SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "DES");        cipher.init(Cipher.DECRYPT_MODE, secretKey);        byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encryptedContent));        return new String(decrypted);    }
}
2. SM4
<dependency>  <groupId>org.bouncycastle</groupId>  <artifactId>bcprov-jdk15on</artifactId>  <version>1.70</version> <!-- You can choose the latest version --></dependency><dependency>  <groupId>org.bouncycastle</groupId>  <artifactId>bcpkix-jdk15on</artifactId>  <version>1.70</version> <!-- You can choose the latest version --></dependency>
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.engines.SM4Engine;
import org.bouncycastle.crypto.modes.ECBBlockCipher;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.util.encoders.Hex;
public class SM4Utils {
    // SM4 encryption and decryption methods    public static byte[] sm4Encrypt(byte[] key, byte[] data) throws CryptoException {        return sm4Process(key, data, true);    }
    public static byte[] sm4Decrypt(byte[] key, byte[] data) throws CryptoException {        return sm4Process(key, data, false);    }
    // Core method for SM4 encryption and decryption    private static byte[] sm4Process(byte[] key, byte[] data, boolean isEncrypt) throws CryptoException {        // Using ECB mode        SM4Engine engine = new SM4Engine();        PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new ECBBlockCipher(engine));
        // Set key        KeyParameter keyParam = new KeyParameter(key);        cipher.init(isEncrypt, keyParam);
        // Perform encryption/decryption operation        byte[] output = new byte[cipher.getOutputSize(data.length)];        int len = cipher.processBytes(data, 0, data.length, output, 0);        cipher.doFinal(output, len);
        return output;    }
    // Convert byte array to hexadecimal string    public static String bytesToHex(byte[] bytes) {        return Hex.toHexString(bytes);    }
    // Convert hexadecimal string to byte array    public static byte[] hexToBytes(String hex) {        return Hex.decode(hex);    }
    public static void main(String[] args) throws CryptoException {        // Example: SM4 encryption and decryption        String key = "1234567890abcdef1234567890abcdef";  // 128-bit key, 16 bytes        String plainText = "Hello SM4 Encryption!"; // Plain text
        // Encrypt        byte[] encrypted = sm4Encrypt(key.getBytes(), plainText.getBytes());        System.out.println("Encrypted (Hex): " + bytesToHex(encrypted));
        // Decrypt        byte[] decrypted = sm4Decrypt(key.getBytes(), encrypted);        System.out.println("Decrypted: " + new String(decrypted));    }}

Hash Algorithms

SHA256 and MD5
import java.security.*;
import java.util.Base64;
public class SignatureUtils {
    // MD5 Signature    public static String signMD5(String content) throws NoSuchAlgorithmException {        MessageDigest md = MessageDigest.getInstance("MD5");        byte[] hash = md.digest(content.getBytes());        return Base64.getEncoder().encodeToString(hash);    }
    // SHA256 Signature    public static String signSHA256(String content) throws NoSuchAlgorithmException {        MessageDigest sha256 = MessageDigest.getInstance("SHA-256");        byte[] hash = sha256.digest(content.getBytes());        return Base64.getEncoder().encodeToString(hash);    }
}
This concludes the content of this article.

👉 If this article has helped you, remember to like + bookmark + share it!

🔥 Welcome to follow the public account 【Lin is Dream】 for more exciting articles!

Leave a Comment