Android 加密知識詳解

还要再努力一些吧發表於2024-11-04

在 Android 開發中,加密技術是確保資料安全的重要手段。本文將詳細介紹幾種常見的加密檔案格式(如 PKCS#12、JKS、BKS)及其用途,以及常用的加密方法(如 X.509 證書和 SHA 雜湊函式),並結合實際應用場景進行講解。

1. keytool 和 OpenSSL 的使用及下載方式

1.1 keytool

keytool 是 Java 開發工具包(JDK)自帶的一個命令列工具,用於建立和管理金鑰庫(keystores)和證書。

下載方式

  • 如果你已經安裝了 JDK,那麼 keytool 已經包含在內。你可以在命令列中直接使用 keytool 命令。
  • 如果沒有安裝 JDK,可以從 Oracle 官方網站下載並安裝 JDK。

常用命令

  1. 生成金鑰對和自簽名證書

    keytool -genkeypair -alias myalias -keyalg RSA -keysize 2048 -keystore mykeystore.jks
    
  2. 檢視金鑰庫內容

    keytool -list -v -keystore mykeystore.jks
    
  3. 匯出證書

    keytool -exportcert -alias myalias -file mycertificate.crt -keystore mykeystore.jks
    
  4. 匯入證書

    keytool -importcert -file mycertificate.crt -alias myalias -keystore mykeystore.jks
    

1.2 OpenSSL

OpenSSL 是一個強大的安全套接字層密碼庫,包含各種密碼演算法、常用的金鑰和證書封裝管理功能以及 SSL 協議,並提供豐富的應用程式供測試或其他目的使用。

下載方式

  • Windows:可以從 OpenSSL 官方網站下載預編譯的二進位制檔案,或者使用 Chocolatey 包管理器安裝。
    choco install openssl
    
  • Linux:大多數 Linux 發行版都預裝了 OpenSSL,如果沒有,可以使用包管理器安裝。
    sudo apt-get install openssl  # Debian/Ubuntu
    sudo yum install openssl      # CentOS/RHEL
    
  • macOS:可以使用 Homebrew 安裝 OpenSSL。
    brew install openssl
    

常用命令

  1. 生成私鑰

    openssl genpkey -algorithm RSA -out private.key
    
  2. 生成自簽名證書

    openssl req -new -x509 -key private.key -out certificate.crt -days 365
    
  3. 生成 CSR(證書籤名請求)

    openssl req -new -key private.key -out request.csr
    
  4. 檢視證書內容

    openssl x509 -in certificate.crt -text -noout
    
  5. 生成 PKCS#12 檔案

    openssl pkcs12 -export -out keystore.p12 -inkey private.key -in certificate.crt -name "alias"
    

2. 金鑰庫格式

2.1 JKS (Java KeyStore)

JSK 是 Java 平臺上的金鑰庫格式,使用 keytool 工具管理。它主要用於儲存金鑰對(私鑰和公鑰)和證書。

示例

  1. 生成金鑰對和自簽名證書

    keytool -genkeypair -alias myalias -keyalg RSA -keysize 2048 -keystore mykeystore.jks
    
  2. 檢視金鑰庫內容

    keytool -list -v -keystore mykeystore.jks
    
  3. 匯出證書

    keytool -exportcert -alias myalias -file mycertificate.crt -keystore mykeystore.jks
    
  4. 匯入證書

    keytool -importcert -file mycertificate.crt -alias myalias -keystore mykeystore.jks
    

2.2 PKCS#12 (P12)

PKCS#12 是國際標準的金鑰庫格式,支援多個證書和金鑰對,使用 openssl 工具管理。它通常用於跨平臺的金鑰庫管理和傳輸。

示例

  1. 生成 PKCS#12 檔案

    openssl pkcs12 -export -out keystore.p12 -inkey private.key -in certificate.crt -name "alias"
    
  2. 檢視 PKCS#12 檔案內容

    openssl pkcs12 -info -in keystore.p12
    
  3. 從 PKCS#12 檔案中提取證書和私鑰

    openssl pkcs12 -in keystore.p12 -out extracted.pem -nodes
    

2.3 BKS (Bouncy Castle KeyStore)

BKS 是由 Bouncy Castle 提供的金鑰庫格式,支援更多演算法,適用於 Android。它提供了比 JKS 更多的安全特性和靈活性。

示例

  1. 生成 BKS 金鑰庫

    keytool -importcert -file certificate.crt -keystore keystore.bks -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider
    
  2. 檢視 BKS 金鑰庫內容

    keytool -list -v -keystore keystore.bks -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider
    

3. 簽名(Signature)

簽名 是一種確保資料完整性和來源真實性的機制。簽名過程通常涉及以下步驟:

  1. 生成雜湊值:使用雜湊函式(如 SHA-256)對資料生成固定長度的雜湊值。
  2. 生成簽名:使用私鑰對雜湊值進行加密,生成簽名。
  3. 驗證簽名:接收方使用公鑰解密簽名,得到雜湊值,並與重新計算的資料雜湊值進行比較,如果一致則簽名有效。

示例

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.MessageDigest;
import java.nio.charset.StandardCharsets;

public class SignatureExample {
    public static void main(String[] args) throws Exception {
        // 生成金鑰對
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(2048);
        KeyPair keyPair = keyGen.generateKeyPair();
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();

        // 生成雜湊值
        String data = "Hello, World!";
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        byte[] hash = md.digest(data.getBytes(StandardCharsets.UTF_8));

        // 生成簽名
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(hash);
        byte[] signedData = signature.sign();

        // 驗證簽名
        signature.initVerify(publicKey);
        signature.update(hash);
        boolean isVerified = signature.verify(signedData);

        System.out.println("Signature verified: " + isVerified);
    }
}

4. 對稱加密(Symmetric Encryption)

對稱加密 使用相同的金鑰進行加密和解密。常見的對稱加密演算法有 AES(Advanced Encryption Standard)、DES(Data Encryption Standard)等。

示例

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class SymmetricEncryptionExample {
    public static void main(String[] args) throws Exception {
        String key = "1234567890123456"; // 16 位元組的金鑰
        String data = "Hello, World!";

        // 加密
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);
        byte[] encryptedData = cipher.doFinal(data.getBytes());
        String encodedEncryptedData = Base64.getEncoder().encodeToString(encryptedData);
        System.out.println("Encrypted Data: " + encodedEncryptedData);

        // 解密
        cipher.init(Cipher.DECRYPT_MODE, keySpec);
        byte[] decodedEncryptedData = Base64.getDecoder().decode(encodedEncryptedData);
        byte[] decryptedData = cipher.doFinal(decodedEncryptedData);
        String originalData = new String(decryptedData);
        System.out.println("Decrypted Data: " + originalData);
    }
}

5. 非對稱加密(Asymmetric Encryption)

非對稱加密 使用一對金鑰(公鑰和私鑰)進行加密和解密。公鑰用於加密,私鑰用於解密。常見的非對稱加密演算法有 RSA、ECC(Elliptic Curve Cryptography)等。

示例

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import javax.crypto.Cipher;
import java.util.Base64;

public class AsymmetricEncryptionExample {
    public static void main(String[] args) throws Exception {
        // 生成金鑰對
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        keyGen.initialize(2048);
        KeyPair keyPair = keyGen.generateKeyPair();
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();

        String data = "Hello, World!";

        // 加密
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] encryptedData = cipher.doFinal(data.getBytes());
        String encodedEncryptedData = Base64.getEncoder().encodeToString(encryptedData);
        System.out.println("Encrypted Data: " + encodedEncryptedData);

        // 解密
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decodedEncryptedData = Base64.getDecoder().decode(encodedEncryptedData);
        byte[] decryptedData = cipher.doFinal(decodedEncryptedData);
        String originalData = new String(decryptedData);
        System.out.println("Decrypted Data: " + originalData);
    }
}

6. 使用 PKCS#12 和 JKS 及 X.509 進行 SSL/TLS 通訊

假設你需要在 Android 應用中使用 PKCS#12 和 JKS 金鑰庫以及 X.509 證書進行 SSL/TLS 通訊。

6.1 生成金鑰庫和證書

6.1.1 生成 PKCS#12 (P12) 金鑰庫

  1. 生成私鑰

    openssl genpkey -algorithm RSA -out private.key
    
  2. 生成自簽名證書

    openssl req -new -x509 -key private.key -out certificate.crt -days 365
    
  3. 生成 PKCS#12 檔案

    openssl pkcs12 -export -out keystore.p12 -inkey private.key -in certificate.crt -name "alias"
    

6.1.2 生成 JKS 金鑰庫

  1. 生成金鑰對和自簽名證書

    keytool -genkeypair -alias myalias -keyalg RSA -keysize 2048 -keystore mykeystore.jks
    
  2. 匯出證書

    keytool -exportcert -alias myalias -file mycertificate.crt -keystore mykeystore.jks
    

6.2 載入金鑰庫並配置 SSLContext

6.2.1 使用 PKCS#12 (P12) 金鑰庫

import java.io.FileInputStream;
import java.security.KeyStore;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;

public class PKCS12SSLConfigurator {
    public static SSLSocketFactory createSSLSocketFactory() throws Exception {
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        try (FileInputStream fis = new FileInputStream("keystore.p12")) {
            keyStore.load(fis, "password".toCharArray());
        }

        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(keyStore, "password".toCharArray());

        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kmf.getKeyManagers(), null, null);

        return sslContext.getSocketFactory();
    }
}

6.2.2 使用 JKS 金鑰庫

import java.io.FileInputStream;
import java.security.KeyStore;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;

public class JKS_SSLConfigurator {
    public static SSLSocketFactory createSSLSocketFactory() throws Exception {
        KeyStore keyStore = KeyStore.getInstance("JKS");
        try (FileInputStream fis = new FileInputStream("mykeystore.jks")) {
            keyStore.load(fis, "password".toCharArray());
        }

        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(keyStore, "password".toCharArray());

        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kmf.getKeyManagers(), null, null);

        return sslContext.getSocketFactory();
    }
}

6.3 使用 SSLSocketFactory 進行 HTTPS 請求

import java.net.URL;
import javax.net.ssl.HttpsURLConnection;

public class Main {
    public static void main(String[] args) {
        try {
            // 使用 PKCS#12 金鑰庫
            SSLSocketFactory sslSocketFactory = PKCS12SSLConfigurator.createSSLSocketFactory();

            // 或者使用 JKS 金鑰庫
            // SSLSocketFactory sslSocketFactory = JKS_SSLConfigurator.createSSLSocketFactory();

            URL url = new URL("https://example.com");
            HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
            connection.setSSLSocketFactory(sslSocketFactory);
            connection.connect();

            // 處理響應
            int responseCode = connection.getResponseCode();
            System.out.println("Response Code: " + responseCode);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

6.4 使用 X.509 證書進行身份驗證

假設你已經有一個 X.509 證書和私鑰,並且需要將其匯入到 PKCS#12 或 JKS 金鑰庫中。

6.4.1 匯入 X.509 證書到 PKCS#12 金鑰庫

  1. 生成 PKCS#12 檔案
    openssl pkcs12 -export -out keystore.p12 -inkey private.key -in certificate.crt -name "alias"
    

6.4.2 匯入 X.509 證書到 JKS 金鑰庫

  1. 生成金鑰對和自簽名證書

    keytool -genkeypair -alias myalias -keyalg RSA -keysize 2048 -keystore mykeystore.jks
    
  2. 匯出證書

    keytool -exportcert -alias myalias -file mycertificate.crt -keystore mykeystore.jks
    
  3. 匯入外部 X.509 證書

    keytool -importcert -file external_certificate.crt -alias externalalias -keystore mykeystore.jks
    

7. X.509 和 SHA 的關係及同類演算法

7.1 X.509 證書

X.509 證書 是一種數字證書標準,用於驗證公鑰的所有權,常用於 SSL/TLS 通訊中的身份驗證。

7.2 SHA (Secure Hash Algorithm)

SHA 是一種雜湊函式,用於生成固定長度的雜湊值,常用於資料完整性校驗和密碼儲存。常見的 SHA 型別有 SHA-1、SHA-256 和 SHA-512。

7.3 關係

  • X.509 證書SHA 在功能上沒有直接關係,但它們經常一起使用:
    • 證書籤名:X.509 證書中的簽名通常使用雜湊函式(如 SHA-256)和非對稱加密演算法(如 RSA)生成。
    • 資料完整性校驗:在傳輸過程中,可以使用 SHA 雜湊值來校驗資料的完整性。

7.4 同類演算法

  • X.509 證書的同類演算法

    • PEM (Privacy Enhanced Mail):一種文字格式,用於編碼 X.509 證書。
    • DER (Distinguished Encoding Rules):一種二進位制格式,用於編碼 X.509 證書。
  • SHA 的同類演算法

    • MD5 (Message-Digest Algorithm 5):生成 128 位雜湊值,現已不推薦使用。
    • SHA-1:生成 160 位雜湊值,已不再被認為是安全的。
    • SHA-256:生成 256 位雜湊值,廣泛使用。
    • SHA-512:生成 512 位雜湊值,提供更高的安全性。

7.5 示例

7.5.1 X.509 證書籤名

假設你有一個 X.509 證書和私鑰,你需要生成一個簽名:

  1. 生成 X.509 證書

    openssl req -new -x509 -key private.key -out certificate.crt -days 365
    
  2. 生成簽名

    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.PrivateKey;
    import java.security.PublicKey;
    import java.security.Signature;
    import java.security.cert.X509Certificate;
    import java.security.cert.CertificateFactory;
    import java.io.FileInputStream;
    
    public class SignatureExample {
        public static void main(String[] args) throws Exception {
            // 生成金鑰對
            KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
            keyGen.initialize(2048);
            KeyPair keyPair = keyGen.generateKeyPair();
            PrivateKey privateKey = keyPair.getPrivate();
            PublicKey publicKey = keyPair.getPublic();
    
            // 載入 X.509 證書
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            try (FileInputStream fis = new FileInputStream("certificate.crt")) {
                X509Certificate certificate = (X509Certificate) cf.generateCertificate(fis);
    
                // 生成簽名
                Signature signature = Signature.getInstance("SHA256withRSA");
                signature.initSign(privateKey);
                byte[] data = "Hello, World!".getBytes();
                signature.update(data);
                byte[] signedData = signature.sign();
    
                // 驗證簽名
                signature.initVerify(publicKey);
                signature.update(data);
                boolean isVerified = signature.verify(signedData);
    
                System.out.println("Signature verified: " + isVerified);
            }
        }
    }
    

7.5.2 資料完整性校驗

假設你需要使用 SHA-256 進行資料完整性校驗:

  1. 生成 SHA-256 雜湊值
    import java.security.MessageDigest;
    import java.nio.charset.StandardCharsets;
    
    public class SHAExample {
        public static void main(String[] args) throws Exception {
            String data = "Hello, World!";
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            byte[] hash = md.digest(data.getBytes(StandardCharsets.UTF_8));
            String hexString = bytesToHex(hash);
            System.out.println("SHA-256 Hash: " + hexString);
        }
    
        private static String bytesToHex(byte[] bytes) {
            StringBuilder sb = new StringBuilder();
            for (byte b : bytes) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        }
    }
    

8 BKS實現HTTPS通訊示例

當然可以!下面是關於如何使用 BKS(Bouncy Castle KeyStore)對接 HTTPS 實現的詳細步驟和示例程式碼。

8.1 準備工作

首先,確保你已經安裝了 Bouncy Castle 提供的 JAR 檔案。你可以從 Bouncy Castle 官方網站下載最新版本的 JAR 檔案,或者透過 Maven 依賴新增到你的專案中。

Maven 依賴

在你的 pom.xml 檔案中新增以下依賴:

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.68</version>
</dependency>

8.2 生成 BKS 金鑰庫

8.2.1 使用 OpenSSL 生成私鑰和自簽名證書

  1. 生成私鑰

    openssl genpkey -algorithm RSA -out private.key
    
  2. 生成自簽名證書

    openssl req -new -x509 -key private.key -out certificate.crt -days 365
    

8.2.2 將證書和私鑰匯入 BKS 金鑰庫

  1. 生成 PKCS#12 檔案

    openssl pkcs12 -export -out keystore.p12 -inkey private.key -in certificate.crt -name "alias"
    
  2. 將 PKCS#12 檔案轉換為 BKS 檔案

    keytool -importkeystore -deststorepass password -destkeypass password -destkeystore keystore.bks -srckeystore keystore.p12 -srcstoretype PKCS12 -srcstorepass password -alias alias
    

8.3 載入 BKS 金鑰庫並配置 SSLContext

8.3.1 建立 BKS 金鑰庫載入器

import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.Security;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class BKSSSLConfigurator {
    static {
        // 新增 Bouncy Castle 提供商
        Security.addProvider(new BouncyCastleProvider());
    }

    public static SSLSocketFactory createSSLSocketFactory() throws Exception {
        KeyStore keyStore = KeyStore.getInstance("BKS", "BC");
        try (FileInputStream fis = new FileInputStream("keystore.bks")) {
            keyStore.load(fis, "password".toCharArray());
        }

        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(keyStore, "password".toCharArray());

        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kmf.getKeyManagers(), null, null);

        return sslContext.getSocketFactory();
    }
}

8.4 使用 SSLSocketFactory 進行 HTTPS 請求

8.4.1 建立主類並進行 HTTPS 請求

import java.net.URL;
import javax.net.ssl.HttpsURLConnection;

public class Main {
    public static void main(String[] args) {
        try {
            // 建立 SSLSocketFactory
            SSLSocketFactory sslSocketFactory = BKSSSLConfigurator.createSSLSocketFactory();

            // 建立 URL 物件
            URL url = new URL("https://example.com");

            // 開啟連線
            HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();

            // 設定 SSLSocketFactory
            connection.setSSLSocketFactory(sslSocketFactory);

            // 連線
            connection.connect();

            // 處理響應
            int responseCode = connection.getResponseCode();
            System.out.println("Response Code: " + responseCode);

            // 讀取響應內容
            try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
                String inputLine;
                StringBuffer content = new StringBuffer();
                while ((inputLine = in.readLine()) != null) {
                    content.append(inputLine);
                }
                System.out.println("Response Content: " + content.toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在加密和安全領域中,“provider”是指提供特定加密演算法和服務的軟體模組。在 Java 中,Provider 是一個介面,定義了一組加密服務(如加密演算法、金鑰生成、簽名等)的實現。每個 Provider 通常是一個獨立的庫或模組,負責實現一組相關的加密功能。

8.5 Provider 的作用

  1. 標準化介面Provider 介面提供了一種標準化的方式來訪問不同的加密演算法和服務,使得開發者不需要關心底層的具體實現細節。
  2. 可插拔性:Java 安全架構允許動態地新增和移除 Provider,這使得系統可以靈活地支援新的加密演算法和服務。
  3. 模組化:每個 Provider 可以專注於實現一組特定的加密功能,這樣可以提高程式碼的可維護性和擴充套件性。

常見的 Provider

  1. Sun Provider:這是 Java 標準庫自帶的預設 Provider,實現了許多常用的加密演算法和服務。
  2. Bouncy Castle Provider:這是一個開源的 Provider,提供了大量的加密演算法和服務,特別適合於需要更多高階加密功能的應用。
  3. SunJSSE Provider:這個 Provider 提供了 Java Secure Socket Extension (JSSE) 的實現,用於支援 SSL/TLS 協議。
  4. SunJCE Provider:這個 Provider 提供了 Java Cryptography Extension (JCE) 的實現,支援更多的加密演算法和服務。

如何使用 Provider

在 Java 中,你可以透過 Security 類來管理和使用 Provider。以下是一些常見的操作:

  1. 獲取所有已註冊的 Provider

    import java.security.Provider;
    import java.security.Security;
    
    public class ListProviders {
        public static void main(String[] args) {
            Provider[] providers = Security.getProviders();
            for (Provider provider : providers) {
                System.out.println(provider.getName());
            }
        }
    }
    
  2. 新增新的 Provider

    import java.security.Security;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    
    public class AddProvider {
        public static void main(String[] args) {
            // 新增 Bouncy Castle Provider
            Security.addProvider(new BouncyCastleProvider());
        }
    }
    
  3. 指定 Provider
    當你需要使用某個特定的 Provider 來執行加密操作時,可以在相關類的方法呼叫中指定 Provider。例如:

    import java.security.KeyPairGenerator;
    import java.security.Security;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    
    public class UseProvider {
        public static void main(String[] args) throws Exception {
            // 新增 Bouncy Castle Provider
            Security.addProvider(new BouncyCastleProvider());
    
            // 使用 Bouncy Castle Provider 生成 RSA 金鑰對
            KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA", "BC");
            keyGen.initialize(2048);
            keyGen.generateKeyPair();
        }
    }
    

示例:使用 Bouncy Castle Provider 進行加密

以下是一個完整的示例,展示瞭如何使用 Bouncy Castle Provider 進行 RSA 加密和解密。

1. 新增 Bouncy Castle 依賴

如果你使用 Maven,可以在 pom.xml 中新增以下依賴:

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.68</version>
</dependency>

2. 使用 Bouncy Castle Provider 進行 RSA 加密和解密

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import javax.crypto.Cipher;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class RSAEncryptionExample {
    static {
        // 新增 Bouncy Castle Provider
        Security.addProvider(new BouncyCastleProvider());
    }

    public static void main(String[] args) throws Exception {
        // 生成金鑰對
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA", "BC");
        keyGen.initialize(2048);
        KeyPair keyPair = keyGen.generateKeyPair();
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();

        // 要加密的資料
        String data = "Hello, World!";
        byte[] plainText = data.getBytes();

        // 加密
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] encryptedData = cipher.doFinal(plainText);

        System.out.println("Encrypted Data: " + bytesToHex(encryptedData));

        // 解密
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decryptedData = cipher.doFinal(encryptedData);
        String decryptedText = new String(decryptedData);

        System.out.println("Decrypted Text: " + decryptedText);
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
}

總結

透過上述解釋和示例程式碼,我們可以看到:

公鑰和私鑰:是一對金鑰,公鑰用於加密和驗證簽名,私鑰用於解密和生成簽名。
加密:使用公鑰對資料進行加密,確保資料的機密性。
非對稱加密:使用一對金鑰(公鑰和私鑰)進行加密和解密,提高了安全性。
簽名:使用私鑰對資料的雜湊值進行加密,生成簽名,確保資料的完整性和來源真實性。

Provider 是 Java 加密框架中的一個重要概念,它提供了一種標準化和模組化的方式來訪問和使用各種加密演算法和服務。透過 Provider,開發者可以靈活地選擇和切換不同的加密實現,從而滿足不同場景下的安全需求。希望這些解釋和示例能夠幫助你更好地理解和使用 Provider。如果有任何問題或需要進一步的解釋,請隨時提問。

透過本文,我們詳細介紹了 keytoolOpenSSL 的使用及下載方式,以及金鑰庫(JKS、PKCS#12、BKS)的格式和用途,簽名、對稱加密和非對稱加密的概念和示例程式碼。這些工具和技術在資料安全和身份驗證中起著重要作用,希望對你在 Android 開發中的加密需求有所幫助!

如果有任何問題或需要進一步的解釋,請隨時留言交流。


相關文章