Algoritmos de criptografia Java - Resumo dos algoritmos de criptografia

Algoritmos de criptografia Java - Resumo dos algoritmos de criptografia

Tal como o algoritmo básico de criptografia unidirecional:

  • A rigor, BASE64 é um formato de codificação, não um algoritmo de criptografia

  • MD5 (algoritmo Message Digest 5, algoritmo de resumo de informações)

  • SHA (Algoritmo de Hash Seguro, algoritmo de hash seguro)

  • HMAC (código de autenticação de mensagem hash, código de autenticação de mensagem hash)

    Criptografia simétrica complexa (DES, PBE), algoritmo de criptografia assimétrica:

  • DES (Data Encryption Standard, algoritmo de criptografia de dados)

  • PBE (criptografia baseada em senha, baseada na autenticação por senha)

  • RSA (o algoritmo leva o nome de seus inventores: Ron Rivest, AdiShamir e Leonard Adleman)

  • DH (algoritmo Diffie-Hellman, protocolo de consenso chave)

  • DSA (Algoritmo de Assinatura Digital, assinatura digital)

  • ECC (criptografia de curvas elípticas, criptografia de curvas elípticas)

    Este artigo apresenta brevemente vários métodos de BASE64 , MD5 , SHA e HMAC . Os três algoritmos de criptografia
    MD5 , SHA e HMAC podem ser descritos como criptografia não reversível, ou seja, um método de criptografia que não pode ser descriptografado. Geralmente os usamos apenas como base para criptografia. A criptografia dos três tipos acima por si só não é confiável.

BASE64
De acordo com a definição de RFC2045, Base64 é definido como: A codificação de transferência de conteúdo Base64 é projetada para descrever qualquer sequência de bytes de 8 bits como uma forma que não é fácil de ser reconhecida diretamente por humanos. (A codificação de transferência de conteúdo Base64 foi projetada para representar sequências arbitrárias de octetos em um formato que não precisa ser legível por humanos.)
Comumente usado em e-mail, criptografia http, interceptação de informações http, você encontrará os campos de nome de usuário e senha para operações de login Criptografado por BASE64.

Vários algoritmos de criptografia Java

Através do código java para conseguir o seguinte:

/**
     * BASE64解密
     * 
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptBASE64(String key) throws Exception {
    
    
        return (new BASE64Decoder()).decodeBuffer(key);
    }
 
    /**
     * BASE64加密
     * 
     * @param key
     * @return
     * @throws Exception
     */
    public static String encryptBASE64(byte[] key) throws Exception {
    
    
        return (new BASE64Encoder()).encodeBuffer(key);
    }

Existem basicamente duas classes de BASE64Encoder e BASE64Decoder, só precisamos saber como usá-las. Além disso, o número de bytes gerados após a criptografia BASE é um múltiplo de 8, se o número de bytes não for suficiente, será preenchido com símbolos **=**.

MD5
MD5 – abreviatura do algoritmo de resumo de mensagens 5 (algoritmo de resumo de informações), amplamente utilizado em tecnologia de criptografia e descriptografia, frequentemente usado na verificação de arquivos. verificar? Não importa o tamanho do arquivo, um valor MD5 exclusivo pode ser gerado após o MD5. Por exemplo, as somas de verificação ISO atuais são todas somas de verificação MD5. Como usar? Obviamente, o valor MD5 é gerado após passar o ISO pelo MD5. Geralmente, amigos que baixam linux-ISO veem strings MD5 ao lado do link de download. É usado para verificar se os arquivos são consistentes.

Vários algoritmos de criptografia Java

Através do código java para conseguir o seguinte:

/**
     * MD5加密
     * 
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] encryptMD5(byte[] data) throws Exception {
    
    
 
        MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);
        md5.update(data);
 
        return md5.digest();
 
    }

Normalmente não usamos a criptografia MD5 acima diretamente. Normalmente, a matriz de bytes gerada pelo MD5 é fornecida ao BASE64 e então criptografada para obter a string correspondente.

SHA
SHA (Secure Hash Algorithm, algoritmo de hash seguro), assinatura digital e outras ferramentas importantes em aplicações de criptografia são amplamente utilizadas no comércio eletrônico e em outras áreas de segurança da informação. Embora tanto o SHA quanto o MD5 tenham sido quebrados pelo método de colisão, o SHA ainda é um algoritmo de criptografia de segurança reconhecido, que é mais seguro que o MD5.

Vários algoritmos de criptografia Java

Através do código java para conseguir o seguinte:

/**
     * SHA加密
     * 
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] encryptSHA(byte[] data) throws Exception {
    
    
 
        MessageDigest sha = MessageDigest.getInstance(KEY_SHA);
        sha.update(data);
 
        return sha.digest();
 
    }
}

HMAC
HMAC (Hash Message Authentication Code, Hash Message Authentication Code, um protocolo de autenticação baseado no algoritmo Hash baseado em chave. O princípio do código de autenticação de mensagem para obter autenticação é usar uma função pública e uma chave para gerar um valor de comprimento fixo como um identificador de autenticação, e use Essa identidade autentica a integridade da mensagem. Use uma chave para gerar um pequeno bloco de dados de tamanho fixo, ou seja, MAC, e adicione-o à mensagem, e então transmita-o. chave compartilhada com o remetente para autenticação e assim por diante.

Vários algoritmos de criptografia Java

Através do código java para conseguir o seguinte:

/**
     * 初始化HMAC密钥
     * 
     * @return
     * @throws Exception
     */
    public static String initMacKey() throws Exception {
    
    
        KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_MAC);
 
        SecretKey secretKey = keyGenerator.generateKey();
        return encryptBASE64(secretKey.getEncoded());
    }
 
    /**
     * HMAC加密
     * 
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] encryptHMAC(byte[] data, String key) throws Exception {
    
    
 
        SecretKey secretKey = new SecretKeySpec(decryptBASE64(key), KEY_MAC);
        Mac mac = Mac.getInstance(secretKey.getAlgorithm());
        mac.init(secretKey);
 
        return mac.doFinal(data);
 
    }

Dada uma classe completa, como segue:

import java.security.MessageDigest;
 
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
 
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
 
/**
 * 基础加密组件
 * 
 * @author 梁栋
 * @version 1.0
 * @since 1.0
 */
public abstract class Coder {
    
    
    public static final String KEY_SHA = "SHA";
    public static final String KEY_MD5 = "MD5";
 
    /**
     * MAC算法可选以下多种算法
     * 
     * <pre>
     * HmacMD5 
     * HmacSHA1 
     * HmacSHA256 
     * HmacSHA384 
     * HmacSHA512
     * </pre>
     */
    public static final String KEY_MAC = "HmacMD5";
 
    /**
     * BASE64解密
     * 
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptBASE64(String key) throws Exception {
    
    
        return (new BASE64Decoder()).decodeBuffer(key);
    }
 
    /**
     * BASE64加密
     * 
     * @param key
     * @return
     * @throws Exception
     */
    public static String encryptBASE64(byte[] key) throws Exception {
    
    
        return (new BASE64Encoder()).encodeBuffer(key);
    }
 
    /**
     * MD5加密
     * 
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] encryptMD5(byte[] data) throws Exception {
    
    
 
        MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);
        md5.update(data);
 
        return md5.digest();
 
    }
 
    /**
     * SHA加密
     * 
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] encryptSHA(byte[] data) throws Exception {
    
    
 
        MessageDigest sha = MessageDigest.getInstance(KEY_SHA);
        sha.update(data);
 
        return sha.digest();
 
    }
 
    /**
     * 初始化HMAC密钥
     * 
     * @return
     * @throws Exception
     */
    public static String initMacKey() throws Exception {
    
    
        KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_MAC);
 
        SecretKey secretKey = keyGenerator.generateKey();
        return encryptBASE64(secretKey.getEncoded());
    }
 
    /**
     * HMAC加密
     * 
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] encryptHMAC(byte[] data, String key) throws Exception {
    
    
 
        SecretKey secretKey = new SecretKeySpec(decryptBASE64(key), KEY_MAC);
        Mac mac = Mac.getInstance(secretKey.getAlgorithm());
        mac.init(secretKey);
 
        return mac.doFinal(data);
 
    }
}

Dê outra aula de teste:

import static org.junit.Assert.*;
 
import org.junit.Test;
 
/**
 * 
 * @author 梁栋
 * @version 1.0
 * @since 1.0
 */
public class CoderTest {
    
    
 
    @Test
    public void test() throws Exception {
    
    
        String inputStr = "简单加密";
        System.err.println("原文:\n" + inputStr);
 
        byte[] inputData = inputStr.getBytes();
        String code = Coder.encryptBASE64(inputData);
 
        System.err.println("BASE64加密后:\n" + code);
 
        byte[] output = Coder.decryptBASE64(code);
 
        String outputStr = new String(output);
 
        System.err.println("BASE64解密后:\n" + outputStr);
 
        // 验证BASE64加密解密一致性
        assertEquals(inputStr, outputStr);
 
        // 验证MD5对于同一内容加密是否一致
        assertArrayEquals(Coder.encryptMD5(inputData), Coder
                .encryptMD5(inputData));
 
        // 验证SHA对于同一内容加密是否一致
        assertArrayEquals(Coder.encryptSHA(inputData), Coder
                .encryptSHA(inputData));
 
        String key = Coder.initMacKey();
        System.err.println("Mac密钥:\n" + key);
 
        // 验证HMAC对于同一内容,同一密钥加密是否一致
        assertArrayEquals(Coder.encryptHMAC(inputData, key), Coder.encryptHMAC(
                inputData, key));
 
        BigInteger md5 = new BigInteger(Coder.encryptMD5(inputData));
        System.err.println("MD5:\n" + md5.toString(16));
 
        BigInteger sha = new BigInteger(Coder.encryptSHA(inputData));
        System.err.println("SHA:\n" + sha.toString(32));
 
        BigInteger mac = new BigInteger(Coder.encryptHMAC(inputData, inputStr));
        System.err.println("HMAC:\n" + mac.toString(16));
    }
}

Saída do console:

原文:
简单加密
BASE64加密后:
566A5Y2V5Yqg5a+G

BASE64解密后:
简单加密
Mac密钥:
uGxdHC+6ylRDaik++leFtGwiMbuYUJ6mqHWyhSgF4trVkVBBSQvY/a22xU8XT1RUemdCWW155Bke
pBIpkd7QHg==

MD5:
-550b4d90349ad4629462113e7934de56
SHA:
91k9vo7p400cjkgfhjh0ia9qthsjagfn
HMAC:
2287d192387e95694bdbba2fa941009a

Nota
Ao compilar, você poderá ver o seguinte prompt:

citar

AVISO: sun.misc.BASE64Decoder é uma API proprietária da Sun e pode ser removida em uma versão futura

import sun.misc.BASE64Decoder;
^
AVISO: sun.misc.BASE64Encoder é uma API proprietária da Sun e pode ser removida em uma versão futura

importar sun.misc.BASE64Encoder;
^

BASE64Encoder e BASE64Decoder são classes de implementação JDK não oficiais. Embora possa ser encontrado e usado no JDK, não pode ser encontrado na API. As classes em pacotes que começam com sun e com.sun no JRE não são documentadas. Elas pertencem à base das bibliotecas de classes java e javax, e a maioria das implementações está relacionada à plataforma subjacente. De modo geral, elas não são recomendadas.

A criptografia e descriptografia do BASE64 são bidirecionais e a solução inversa pode ser obtida.
MD5, SHA e HMAC são criptografia unidirecional. Qualquer dado criptografado gerará apenas uma string criptografada exclusiva, que geralmente é usada para verificar se os dados foram modificados durante a transmissão. Dentre eles, o algoritmo HMAC possui uma chave, que aumenta a segurança durante a transmissão de dados e fortalece os fatores incontroláveis ​​​​fora do algoritmo.
O objetivo da criptografia unidirecional é principalmente verificar se os dados foram modificados durante a transmissão.

A seguir apresentamos o algoritmo de criptografia simétrica, o mais comumente usado é o algoritmo de criptografia de dados DES.
DES
DES-Data Encryption Standard, o algoritmo de criptografia de dados. Foi pesquisado e publicado com sucesso pela IBM em 1975. Existem três parâmetros de entrada do algoritmo DES: Chave, Dados e Modo. Entre eles, a chave tem 8 bytes e 64 bits no total, que é a chave de trabalho do algoritmo DES; os dados também têm 8 bytes e 64 bits, que são os dados a serem criptografados ou descriptografados; o modo é o modo de trabalho do DES, e existem dois tipos: criptografar ou descriptografar.
O algoritmo DES transforma um bloco de entrada de texto simples de 64 bits em um bloco de saída de texto cifrado de 64 bits, e a chave que ele usa também é de 64 bits.

Através do código java para conseguir o seguinte: classe Coder veja

import java.security.Key;
import java.security.SecureRandom;
 
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
 
 
/**
 * DES安全编码组件
 * 
 * <pre>
 * 支持 DES、DESede(TripleDES,就是3DES)、AES、Blowfish、RC2、RC4(ARCFOUR)
 * DES                  key size must be equal to 56
 * DESede(TripleDES)     key size must be equal to 112 or 168
 * AES                  key size must be equal to 128, 192 or 256,but 192 and 256 bits may not be available
 * Blowfish          key size must be multiple of 8, and can only range from 32 to 448 (inclusive)
 * RC2                  key size must be between 40 and 1024 bits
 * RC4(ARCFOUR)      key size must be between 40 and 1024 bits
 * 具体内容 需要关注 JDK Document http://.../docs/technotes/guides/security/SunProviders.html
 * </pre>
 * 
 * @author 梁栋
 * @version 1.0
 * @since 1.0
 */
public abstract class DESCoder extends Coder {
    
    
    /**
     * ALGORITHM 算法 <br>
     * 可替换为以下任意一种算法,同时key值的size相应改变。
     * 
     * <pre>
     * DES                  key size must be equal to 56
     * DESede(TripleDES)     key size must be equal to 112 or 168
     * AES                  key size must be equal to 128, 192 or 256,but 192 and 256 bits may not be available
     * Blowfish          key size must be multiple of 8, and can only range from 32 to 448 (inclusive)
     * RC2                  key size must be between 40 and 1024 bits
     * RC4(ARCFOUR)      key size must be between 40 and 1024 bits
     * </pre>
     * 
     * 在Key toKey(byte[] key)方法中使用下述代码
     * <code>SecretKey secretKey = new SecretKeySpec(key, ALGORITHM);</code> 替换
     * <code>
     * DESKeySpec dks = new DESKeySpec(key);
     * SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
     * SecretKey secretKey = keyFactory.generateSecret(dks);
     * </code>
     */
    public static final String ALGORITHM = "DES";
 
    /**
     * 转换密钥<br>
     * 
     * @param key
     * @return
     * @throws Exception
     */
    private static Key toKey(byte[] key) throws Exception {
    
    
        DESKeySpec dks = new DESKeySpec(key);
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
        SecretKey secretKey = keyFactory.generateSecret(dks);
 
        // 当使用其他对称加密算法时,如AES、Blowfish等算法时,用下述代码替换上述三行代码
        // SecretKey secretKey = new SecretKeySpec(key, ALGORITHM);
 
        return secretKey;
    }
 
    /**
     * 解密
     * 
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decrypt(byte[] data, String key) throws Exception {
    
    
        Key k = toKey(decryptBASE64(key));
 
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, k);
 
        return cipher.doFinal(data);
    }
 
    /**
     * 加密
     * 
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] encrypt(byte[] data, String key) throws Exception {
    
    
        Key k = toKey(decryptBASE64(key));
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, k);
 
        return cipher.doFinal(data);
    }
 
    /**
     * 生成密钥
     * 
     * @return
     * @throws Exception
     */
    public static String initKey() throws Exception {
    
    
        return initKey(null);
    }
 
    /**
     * 生成密钥
     * 
     * @param seed
     * @return
     * @throws Exception
     */
    public static String initKey(String seed) throws Exception {
    
    
        SecureRandom secureRandom = null;
 
        if (seed != null) {
    
    
            secureRandom = new SecureRandom(decryptBASE64(seed));
        } else {
    
    
            secureRandom = new SecureRandom();
        }
 
        KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM);
        kg.init(secureRandom);
 
        SecretKey secretKey = kg.generateKey();
 
        return encryptBASE64(secretKey.getEncoded());
    }
}

Continuando a implementação da classe anterior, usamos MD5 e SHA para criptografar strings para gerar chaves, que é um método de geração de chaves relativamente comum.
Dê outra aula de teste:

import static org.junit.Assert.*;
 
 
import org.junit.Test;
 
/**
 * 
 * @author 梁栋
 * @version 1.0
 * @since 1.0
 */
public class DESCoderTest {
    
    
 
    @Test
    public void test() throws Exception {
    
    
        String inputStr = "DES";
        String key = DESCoder.initKey();
        System.err.println("原文:\t" + inputStr);
 
        System.err.println("密钥:\t" + key);
 
        byte[] inputData = inputStr.getBytes();
        inputData = DESCoder.encrypt(inputData, key);
 
        System.err.println("加密后:\t" + DESCoder.encryptBASE64(inputData));
 
        byte[] outputData = DESCoder.decrypt(inputData, key);
        String outputStr = new String(outputData);
 
        System.err.println("解密后:\t" + outputStr);
 
        assertEquals(inputStr, outputStr);
    }
}

A saída resultante é a seguinte:

原文:	DES
密钥:	f3wEtRrV6q0=

加密后:	C6qe9oNIzRY=

解密后:	DES

A saída obtida do console, podemos comparar os resultados após criptografia e descriptografia. Este é um método simples de criptografia e descriptografia com apenas uma chave.
Na verdade, DES tem muitos irmãos, como DESede (TripleDES), AES, Blowfish, RC2, RC4 (ARCFOUR). Não vou elaborar muito aqui, é a mesma coisa, basta substituir o ALGORITMO pelo valor correspondente, e ao mesmo tempo fazer um código para substituir **SecretKey secretKey = new SecretKeySpec(key, ALGORITHM);** Está tudo bem e o comprimento da chave é diferente.

/**
 * DES          key size must be equal to 56
 * DESede(TripleDES) key size must be equal to 112 or 168
 * AES          key size must be equal to 128, 192 or 256,but 192 and 256 bits may not be available
 * Blowfish     key size must be multiple of 8, and can only range from 32 to 448 (inclusive)
 * RC2          key size must be between 40 and 1024 bits
 * RC4(ARCFOUR) key size must be between 40 and 1024 bits
 **/

Além do DES, também sabemos que existem DESede (TripleDES, ou seja, 3DES), AES, Blowfish, RC2, RC4 (ARCFOUR) e outros métodos de criptografia simétrica, e seus métodos de implementação são semelhantes. Aqui está outro algoritmo para simetria criptografia —— PBE
PBE
PBE - Criptografia baseada em senha (com base na criptografia de senha). Sua característica é que a senha é controlada pelo usuário sem qualquer meio físico; métodos como hash de números aleatórios (aqui chamamos de salt) e criptografia múltipla são utilizados para garantir a segurança dos dados. É um método de criptografia simples.
Através do código java para conseguir o seguinte: classe Coder veja

import java.security.Key;
import java.util.Random;
  
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
  
/**
 * PBE安全编码组件
 * 
 * @author 梁栋
 * @version 1.0
 * @since 1.0
 */
public abstract class PBECoder extends Coder {
    
    
    /**
     * 支持以下任意一种算法
     * 
     * <pre>
     * PBEWithMD5AndDES 
     * PBEWithMD5AndTripleDES 
     * PBEWithSHA1AndDESede
     * PBEWithSHA1AndRC2_40
     * </pre>
     */
    public static final String ALGORITHM = "PBEWITHMD5andDES";
  
    /**
     * 盐初始化
     * 
     * @return
     * @throws Exception
     */
    public static byte[] initSalt() throws Exception {
    
    
        byte[] salt = new byte[8];
        Random random = new Random();
        random.nextBytes(salt);
        return salt;
    }
  
    /**
     * 转换密钥<br>
     * 
     * @param password
     * @return
     * @throws Exception
     */
    private static Key toKey(String password) throws Exception {
    
    
        PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
        SecretKey secretKey = keyFactory.generateSecret(keySpec);
  
        return secretKey;
    }
  
    /**
     * 加密
     * 
     * @param data 数据
     * @param password 密码
     * @param salt  盐
     * @return
     * @throws Exception
     */
    public static byte[] encrypt(byte[] data, String password, byte[] salt)
            throws Exception {
    
    
  
        Key key = toKey(password);
  
        PBEParameterSpec paramSpec = new PBEParameterSpec(salt, 100);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
  
        return cipher.doFinal(data);
  
    }
  
    /**
     * 解密
     * 
     * @param data  数据
     * @param password 密码
     * @param salt  盐
     * @return
     * @throws Exception
     */
    public static byte[] decrypt(byte[] data, String password, byte[] salt)
            throws Exception {
    
    
  
        Key key = toKey(password);
  
        PBEParameterSpec paramSpec = new PBEParameterSpec(salt, 100);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
  
        return cipher.doFinal(data);
  
    }
}

Dê outra aula de teste:

import static org.junit.Assert.*;
  
import org.junit.Test;
  
/**
 * 
 * @author 梁栋
 * @version 1.0
 * @since 1.0
 */
public class PBECoderTest {
    
    
  
    @Test
    public void test() throws Exception {
    
    
        String inputStr = "abc";
        System.err.println("原文: " + inputStr);
        byte[] input = inputStr.getBytes();
  
        String pwd = "efg";
        System.err.println("密码: " + pwd);
  
        byte[] salt = PBECoder.initSalt();
  
        byte[] data = PBECoder.encrypt(input, pwd, salt);
  
        System.err.println("加密后: " + PBECoder.encryptBASE64(data));
  
        byte[] output = PBECoder.decrypt(data, pwd, salt);
        String outputStr = new String(output);
  
        System.err.println("解密后: " + outputStr);
        assertEquals(inputStr, outputStr);
    }
  
}

Saída do console:

原文: abc
密码: efg
加密后: iCZ0uRtaAhE=
 
解密后: abc

Posteriormente apresentaremos algoritmos de criptografia assimétrica, como RSA, DSA, DH, ECC, etc.

A seguir, apresentamos um algoritmo típico de criptografia assimétrica - RSA

O algoritmo RSA
apareceu em 1978. É o primeiro algoritmo que pode ser usado tanto para criptografia de dados quanto para assinatura digital. É fácil de entender e operar e também é popular. Os algoritmos recebem o nome de seus inventores: Ron Rivest, AdiShamir e Leonard Adleman.
A característica deste algoritmo de criptografia é principalmente a mudança da chave. Vimos acima que o DES possui apenas uma chave. É equivalente a apenas uma chave. Se a chave for perdida, os dados não estarão seguros. RSA possui duas chaves ao mesmo tempo, chave pública e chave privada. Também suporta assinaturas digitais. A importância da assinatura digital é verificar os dados transmitidos. Certifique-se de que os dados não sejam modificados durante o projeto de transferência.

Análise de processo:

  1. A Parte A constrói um par de chaves, publica a chave pública para a Parte B e mantém a chave privada.
  2. A Parte A criptografa os dados com a chave privada, depois assina os dados criptografados com a chave privada e envia a assinatura e os dados criptografados para a Parte B; A Parte B usa a chave pública e a assinatura para verificar se os dados a serem descriptografados são válidos, e se a chave pública for usada de forma eficaz para descriptografar.
  3. A Parte B criptografa os dados com a chave pública e envia os dados criptografados para a Parte A; a Parte A obtém os dados criptografados e os descriptografa com a chave privada.

De acordo com as etapas acima, o diagrama de sequência é fornecido da seguinte forma:

  1. Vários algoritmos de criptografia Java
  2. Vários algoritmos de criptografia Java
  3. Vários algoritmos de criptografia Java

Através do código java para conseguir o seguinte: classe Coder veja

import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
 
import java.util.HashMap;
import java.util.Map;
 
import javax.crypto.Cipher;
 
/**
 * RSA安全编码组件
 * 
 * @author 梁栋
 * @version 1.0
 * @since 1.0
 */
public abstract class RSACoder extends Coder {
    
    
    public static final String KEY_ALGORITHM = "RSA";
    public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
 
    private static final String PUBLIC_KEY = "RSAPublicKey";
    private static final String PRIVATE_KEY = "RSAPrivateKey";
 
    /**
     * 用私钥对信息生成数字签名
     * 
     * @param data
     *            加密数据
     * @param privateKey
     *            私钥
     * 
     * @return
     * @throws Exception
     */
    public static String sign(byte[] data, String privateKey) throws Exception {
    
    
        // 解密由base64编码的私钥
        byte[] keyBytes = decryptBASE64(privateKey);
 
        // 构造PKCS8EncodedKeySpec对象
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
 
        // KEY_ALGORITHM 指定的加密算法
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
 
        // 取私钥匙对象
        PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
 
        // 用私钥对信息生成数字签名
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initSign(priKey);
        signature.update(data);
 
        return encryptBASE64(signature.sign());
    }
 
    /**
     * 校验数字签名
     * 
     * @param data
     *            加密数据
     * @param publicKey
     *            公钥
     * @param sign
     *            数字签名
     * 
     * @return 校验成功返回true 失败返回false
     * @throws Exception
     * 
     */
    public static boolean verify(byte[] data, String publicKey, String sign)
            throws Exception {
    
    
 
        // 解密由base64编码的公钥
        byte[] keyBytes = decryptBASE64(publicKey);
 
        // 构造X509EncodedKeySpec对象
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
 
        // KEY_ALGORITHM 指定的加密算法
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
 
        // 取公钥匙对象
        PublicKey pubKey = keyFactory.generatePublic(keySpec);
 
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initVerify(pubKey);
        signature.update(data);
 
        // 验证签名是否正常
        return signature.verify(decryptBASE64(sign));
    }
 
    /**
     * 解密<br>
     * 用私钥解密
     * 
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPrivateKey(byte[] data, String key)
            throws Exception {
    
    
        // 对密钥解密
        byte[] keyBytes = decryptBASE64(key);
 
        // 取得私钥
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
 
        // 对数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
 
        return cipher.doFinal(data);
    }
 
    /**
     * 解密<br>
     * 用私钥解密
     * 
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPublicKey(byte[] data, String key)
            throws Exception {
    
    
        // 对密钥解密
        byte[] keyBytes = decryptBASE64(key);
 
        // 取得公钥
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicKey = keyFactory.generatePublic(x509KeySpec);
 
        // 对数据解密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
 
        return cipher.doFinal(data);
    }
 
    /**
     * 加密<br>
     * 用公钥加密
     * 
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPublicKey(byte[] data, String key)
            throws Exception {
    
    
        // 对公钥解密
        byte[] keyBytes = decryptBASE64(key);
 
        // 取得公钥
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicKey = keyFactory.generatePublic(x509KeySpec);
 
        // 对数据加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
 
        return cipher.doFinal(data);
    }
 
    /**
     * 加密<br>
     * 用私钥加密
     * 
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPrivateKey(byte[] data, String key)
            throws Exception {
    
    
        // 对密钥解密
        byte[] keyBytes = decryptBASE64(key);
 
        // 取得私钥
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
 
        // 对数据加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
 
        return cipher.doFinal(data);
    }
 
    /**
     * 取得私钥
     * 
     * @param keyMap
     * @return
     * @throws Exception
     */
    public static String getPrivateKey(Map<String, Object> keyMap)
            throws Exception {
    
    
        Key key = (Key) keyMap.get(PRIVATE_KEY);
 
        return encryptBASE64(key.getEncoded());
    }
 
    /**
     * 取得公钥
     * 
     * @param keyMap
     * @return
     * @throws Exception
     */
    public static String getPublicKey(Map<String, Object> keyMap)
            throws Exception {
    
    
        Key key = (Key) keyMap.get(PUBLIC_KEY);
 
        return encryptBASE64(key.getEncoded());
    }
 
    /**
     * 初始化密钥
     * 
     * @return
     * @throws Exception
     */
    public static Map<String, Object> initKey() throws Exception {
    
    
        KeyPairGenerator keyPairGen = KeyPairGenerator
                .getInstance(KEY_ALGORITHM);
        keyPairGen.initialize(1024);
 
        KeyPair keyPair = keyPairGen.generateKeyPair();
 
        // 公钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
 
        // 私钥
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
 
        Map<String, Object> keyMap = new HashMap<String, Object>(2);
 
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;
    }
}

Dê outra aula de teste:

import static org.junit.Assert.*;
 
import org.junit.Before;
import org.junit.Test;
 
import java.util.Map;
 
/**
 * 
 * @author 梁栋
 * @version 1.0
 * @since 1.0
 */
public class RSACoderTest {
    
    
    private String publicKey;
    private String privateKey;
 
    @Before
    public void setUp() throws Exception {
    
    
        Map<String, Object> keyMap = RSACoder.initKey();
 
        publicKey = RSACoder.getPublicKey(keyMap);
        privateKey = RSACoder.getPrivateKey(keyMap);
        System.err.println("公钥: \n\r" + publicKey);
        System.err.println("私钥: \n\r" + privateKey);
    }
 
    @Test
    public void test() throws Exception {
    
    
        System.err.println("公钥加密——私钥解密");
        String inputStr = "abc";
        byte[] data = inputStr.getBytes();
 
        byte[] encodedData = RSACoder.encryptByPublicKey(data, publicKey);
 
        byte[] decodedData = RSACoder.decryptByPrivateKey(encodedData,
                privateKey);
 
        String outputStr = new String(decodedData);
        System.err.println("加密前: " + inputStr + "\n\r" + "解密后: " + outputStr);
        assertEquals(inputStr, outputStr);
 
    }
 
    @Test
    public void testSign() throws Exception {
    
    
        System.err.println("私钥加密——公钥解密");
        String inputStr = "sign";
        byte[] data = inputStr.getBytes();
 
        byte[] encodedData = RSACoder.encryptByPrivateKey(data, privateKey);
 
        byte[] decodedData = RSACoder
                .decryptByPublicKey(encodedData, publicKey);
 
        String outputStr = new String(decodedData);
        System.err.println("加密前: " + inputStr + "\n\r" + "解密后: " + outputStr);
        assertEquals(inputStr, outputStr);
 
        System.err.println("私钥签名——公钥验证签名");
        // 产生签名
        String sign = RSACoder.sign(encodedData, privateKey);
        System.err.println("签名:\r" + sign);
 
        // 验证签名
        boolean status = RSACoder.verify(encodedData, publicKey, sign);
        System.err.println("状态:\r" + status);
        assertTrue(status);
 
    }
 
}

Saída do console:

公钥: 

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCYU/+I0+z1aBl5X6DUUOHQ7FZpmBSDbKTtx89J
EcB64jFCkunELT8qiKly7fzEqD03g8ALlu5XvX+bBqHFy7YPJJP0ekE2X3wjUnh2NxlqpH3/B/xm
1ZdSlCwDIkbijhBVDjA/bu5BObhZqQmDwIxlQInL9oVz+o6FbAZCyHBd7wIDAQAB

私钥: 

MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJhT/4jT7PVoGXlfoNRQ4dDsVmmY
FINspO3Hz0kRwHriMUKS6cQtPyqIqXLt/MSoPTeDwAuW7le9f5sGocXLtg8kk/R6QTZffCNSeHY3
GWqkff8H/GbVl1KULAMiRuKOEFUOMD9u7kE5uFmpCYPAjGVAicv2hXP6joVsBkLIcF3vAgMBAAEC
gYBvZHWoZHmS2EZQqKqeuGr58eobG9hcZzWQoJ4nq/CarBAjw/VovUHE490uK3S9ht4FW7Yzg3LV
/MB06Huifh6qf/X9NQA7SeZRRC8gnCQk6JuDIEVJOud5jU+9tyumJakDKodQ3Jf2zQtNr+5ZdEPl
uwWgv9c4kmpjhAdyMuQmYQJBANn6pcgvyYaia52dnu+yBUsGkaFfwXkzFSExIbi0MXTkhEb/ER/D
rLytukkUu5S5ecz/KBa8U4xIslZDYQbLz5ECQQCy5dutt7RsxN4+dxCWn0/1FrkWl2G329Ucewm3
QU9CKu4D+7Kqdj+Ha3lXP8F0Etaaapi7+EfkRUpukn2ItZV/AkEAlk+I0iphxT1rCB0Q5CjWDY5S
Df2B5JmdEG5Y2o0nLXwG2w44OLct/k2uD4cEcuITY5Dvi/4BftMCZwm/dnhEgQJACIktJSnJwxLV
o9dchENPtlsCM9C/Sd2EWpqISSUlmfugZbJBwR5pQ5XeMUqKeXZYpP+HEBj1nS+tMH9u2/IGEwJA
fL8mZiZXan/oBKrblAbplNcKWGRVD/3y65042PAEeghahlJMiYquV5DzZajuuT0wbJ5xQuZB01+X
nfpFpBJ2dw==

公钥加密——私钥解密
加密前: abc

解密后: abc
公钥: 

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdOj40yEB48XqWxmPILmJAc7UecIN7F32etSHF
9rwbuEh3+iTPOGSxhoSQpOED0vOb0ZIMkBXZSgsxLaBSin2RZ09YKWRjtpCA0kDkiD11gj4tzTiM
l9qq1kwSK7ZkGAgodEn3yIILVmQDuEImHOXFtulvJ71ka07u3LuwUNdB/wIDAQAB

私钥: 

MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAN06PjTIQHjxepbGY8guYkBztR5w
g3sXfZ61IcX2vBu4SHf6JM84ZLGGhJCk4QPS85vRkgyQFdlKCzEtoFKKfZFnT1gpZGO2kIDSQOSI
PXWCPi3NOIyX2qrWTBIrtmQYCCh0SffIggtWZAO4QiYc5cW26W8nvWRrTu7cu7BQ10H/AgMBAAEC
gYEAz2JWBizjI31bqhP4XiP9PuY5F3vqBW4T+L9cFbQiyumKJc58yzTWUAUGKIIn3enXLG7dNqGr
mbJro4JeFIJ3CiVDpXR9+FluIgI4SXm7ioGKF2NOMA9LR5Fu82W+pLfpTN2y2SaLYWEDZyp53BxY
j9gUxaxi1MQs+C1ZgDF2xmECQQDy70bQntbRfysP+ppCtd56YRnES1Tyekw0wryS2tr+ivQJl7JF
gp5rPAOXpgrq36xHDwUspQ0sJ0vj0O7ywxr1AkEA6SAaLhrJJrYucC0jxwAhUYyaPN+aOsWymaRh
9jA/Wc0wp29SbGTh5CcMuGpXm1g0M+FKW3dGiHgS3rVUKim4owJAbnxgapUzAgiiHxxMeDaavnHW
9C2GrtjsO7qtZOTgYI/1uT8itvZW8lJTF+9OW8/qXE76fXl7ai9dFnl5kzMk2QJBALfHz/vCsArt
mkRiwY6zApE4Z6tPl1V33ymSVovvUzHnOdD1SKQdD5t+UV/crb3QVi8ED0t2B0u0ZSPfDT/D7kMC
QDpwdj9k2F5aokLHBHUNJPFDAp7a5QMaT64gv/d48ITJ68Co+v5WzLMpzJBYXK6PAtqIhxbuPEc2
I2k1Afmrwyw=

私钥加密——公钥解密
加密前: sign

解密后: sign
私钥签名——公钥验证签名
签名:
ud1RsIwmSC1pN22I4IXteg1VD2FbiehKUfNxgVSHzvQNIK+d20FCkHCqh9djP3h94iWnIUY0ifU+
mbJkhAl/i5krExOE0hknOnPMcEP+lZV1RbJI2zG2YooSp2XDleqrQk5e/QF2Mx0Zxt8Xsg7ucVpn
i3wwbYWs9wSzIf0UjlM=

状态:
true

Para resumir brevemente, usando criptografia de chave pública e descriptografia de chave privada, uma transferência de dados da Parte B para a Parte A é concluída, por meio de criptografia de chave privada, descriptografia de chave pública e, ao mesmo tempo, por meio de assinatura de chave privada e assinatura de verificação de chave pública, é concluída uma transmissão de dados da Parte A para a Parte A. Transferência e verificação de dados da Parte B, duas transferências de dados completam um conjunto completo de interação de dados!

Semelhante às assinaturas digitais, os envelopes digitais são descritos a seguir:

Envelopes digitais
Os envelopes digitais usam criptografia para garantir que apenas o destinatário pretendido possa ler o conteúdo da carta.
Processo:
O remetente da informação usa uma chave simétrica para criptografar a informação e, em seguida, usa a chave pública do destinatário para criptografar a chave simétrica (esta parte é chamada de envelope digital) e, em seguida, envia-a ao destinatário junto com a informação; o receptor primeiro abra o envelope digital com a chave privada correspondente para obter a chave simétrica e, em seguida, use a chave simétrica para descriptografar as informações.

A seguir analisamos o algoritmo de criptografia DH, um algoritmo de criptografia baseado em um protocolo de acordo de chave. Algoritmo
DH Diffie-Hellman (algoritmo DH), protocolo de consenso chave.
É uma ideia proposta por Diffie e Hellman, os fundadores do criptossistema de chave pública. Simplificando, permite que dois usuários troquem informações em meios públicos para gerar uma chave “consistente” que pode ser compartilhada. Em outras palavras, a Parte A produz um par de chaves (chave pública, chave privada) e a Parte B gera um par de chaves (chave pública, chave privada) da Parte B de acordo com a chave pública da Parte A. Esta é a linha de base e a base para a confidencialidade da transmissão de dados. Ao mesmo tempo, ambas as partes usam o mesmo algoritmo de criptografia simétrica para construir uma chave local (SecretKey) para criptografar os dados. Desta forma, após a troca do algoritmo de chave local (SecretKey), a Parte A e a Parte B divulgam suas chaves públicas, usam a chave pública da outra parte e a chave privada recém-gerada para criptografar os dados e, ao mesmo tempo, usam a chave pública da outra parte chave e sua própria chave privada para criptografar dados. Não apenas as duas partes, Parte A e Parte B, mas também podem ser expandidas para comunicação de dados compartilhada entre várias partes, completando assim a comunicação segura de dados interativos em rede! O algoritmo é derivado do teorema da congruência chinês - o teorema do resto chinês.

Análise de processo:

1. A Parte A constrói um par de chaves, anuncia a chave pública à Parte B e mantém a chave privada; as duas partes concordam com um algoritmo de criptografia de dados; chave reservada.
2. A Parte A usa a chave privada, a chave pública da Parte B e o algoritmo de criptografia de dados acordado para construir uma chave local, depois criptografa os dados com a chave local e envia os dados criptografados para a Parte B; a Parte B usa a chave privada , A chave pública da Parte A e os dados acordados para criptografar O algoritmo constrói uma chave local e, em seguida, descriptografa os dados por meio da chave local.
3. A Parte B usa a chave privada, a chave pública da Parte A e o algoritmo de criptografia de dados acordado para construir uma chave local, depois criptografa os dados com a chave local e envia os dados criptografados para a Parte A; a Parte A usa a chave privada , A chave pública da Parte B e os dados acordados O algoritmo de criptografia constrói uma chave local e, em seguida, descriptografa os dados por meio da chave local.

Vários algoritmos de criptografia Java

  1. Vários algoritmos de criptografia Java
  2. Vários algoritmos de criptografia Java

Através do código java para conseguir o seguinte: classe Coder veja

import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
 
import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHPrivateKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
 
/**
 * DH安全编码组件
 * 
 * @author 梁栋
 * @version 1.0
 * @since 1.0
 */
public abstract class DHCoder extends Coder {
    
    
    public static final String ALGORITHM = "DH";
 
    /**
     * 默认密钥字节数
     * 
     * <pre>
     * DH
     * Default Keysize 1024  
     * Keysize must be a multiple of 64, ranging from 512 to 1024 (inclusive).
     * </pre>
     */
    private static final int KEY_SIZE = 1024;
 
    /**
     * DH加密下需要一种对称加密算法对数据加密,这里我们使用DES,也可以使用其他对称加密算法。
     */
    public static final String SECRET_ALGORITHM = "DES";
    private static final String PUBLIC_KEY = "DHPublicKey";
    private static final String PRIVATE_KEY = "DHPrivateKey";
 
    /**
     * 初始化甲方密钥
     * 
     * @return
     * @throws Exception
     */
    public static Map<String, Object> initKey() throws Exception {
    
    
        KeyPairGenerator keyPairGenerator = KeyPairGenerator
                .getInstance(ALGORITHM);
        keyPairGenerator.initialize(KEY_SIZE);
 
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
 
        // 甲方公钥
        DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic();
 
        // 甲方私钥
        DHPrivateKey privateKey = (DHPrivateKey) keyPair.getPrivate();
 
        Map<String, Object> keyMap = new HashMap<String, Object>(2);
 
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;
    }
 
    /**
     * 初始化乙方密钥
     * 
     * @param key
     *            甲方公钥
     * @return
     * @throws Exception
     */
    public static Map<String, Object> initKey(String key) throws Exception {
    
    
        // 解析甲方公钥
        byte[] keyBytes = decryptBASE64(key);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
 
        // 由甲方公钥构建乙方密钥
        DHParameterSpec dhParamSpec = ((DHPublicKey) pubKey).getParams();
 
        KeyPairGenerator keyPairGenerator = KeyPairGenerator
                .getInstance(keyFactory.getAlgorithm());
        keyPairGenerator.initialize(dhParamSpec);
 
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
 
        // 乙方公钥
        DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic();
 
        // 乙方私钥
        DHPrivateKey privateKey = (DHPrivateKey) keyPair.getPrivate();
 
        Map<String, Object> keyMap = new HashMap<String, Object>(2);
 
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
 
        return keyMap;
    }
 
    /**
     * 加密<br>
     * 
     * @param data
     *            待加密数据
     * @param publicKey
     *            甲方公钥
     * @param privateKey
     *            乙方私钥
     * @return
     * @throws Exception
     */
    public static byte[] encrypt(byte[] data, String publicKey,
            String privateKey) throws Exception {
    
    
 
        // 生成本地密钥
        SecretKey secretKey = getSecretKey(publicKey, privateKey);
 
        // 数据加密
        Cipher cipher = Cipher.getInstance(secretKey.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
 
        return cipher.doFinal(data);
    }
 
    /**
     * 解密<br>
     * 
     * @param data
     *            待解密数据
     * @param publicKey
     *            乙方公钥
     * @param privateKey
     *            乙方私钥
     * @return
     * @throws Exception
     */
    public static byte[] decrypt(byte[] data, String publicKey,
            String privateKey) throws Exception {
    
    
 
        // 生成本地密钥
        SecretKey secretKey = getSecretKey(publicKey, privateKey);
        // 数据解密
        Cipher cipher = Cipher.getInstance(secretKey.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
 
        return cipher.doFinal(data);
    }
 
    /**
     * 构建密钥
     * 
     * @param publicKey
     *            公钥
     * @param privateKey
     *            私钥
     * @return
     * @throws Exception
     */
    private static SecretKey getSecretKey(String publicKey, String privateKey)
            throws Exception {
    
    
        // 初始化公钥
        byte[] pubKeyBytes = decryptBASE64(publicKey);
 
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKeyBytes);
        PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
 
        // 初始化私钥
        byte[] priKeyBytes = decryptBASE64(privateKey);
 
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKeyBytes);
        Key priKey = keyFactory.generatePrivate(pkcs8KeySpec);
 
        KeyAgreement keyAgree = KeyAgreement.getInstance(keyFactory
                .getAlgorithm());
        keyAgree.init(priKey);
        keyAgree.doPhase(pubKey, true);
 
        // 生成本地密钥
        SecretKey secretKey = keyAgree.generateSecret(SECRET_ALGORITHM);
 
        return secretKey;
    }
 
    /**
     * 取得私钥
     * 
     * @param keyMap
     * @return
     * @throws Exception
     */
    public static String getPrivateKey(Map<String, Object> keyMap)
            throws Exception {
    
    
        Key key = (Key) keyMap.get(PRIVATE_KEY);
 
        return encryptBASE64(key.getEncoded());
    }
 
    /**
     * 取得公钥
     * 
     * @param keyMap
     * @return
     * @throws Exception
     */
    public static String getPublicKey(Map<String, Object> keyMap)
            throws Exception {
    
    
        Key key = (Key) keyMap.get(PUBLIC_KEY);
 
        return encryptBASE64(key.getEncoded());
    }
}

Dê outra aula de teste:

import static org.junit.Assert.*;
 
import java.util.Map;
 
import org.junit.Test;
 
/**
 * 
 * @author 梁栋
 * @version 1.0
 * @since 1.0
 */
public class DHCoderTest {
    
    
 
    @Test
    public void test() throws Exception {
    
    
        // 生成甲方密钥对儿
        Map<String, Object> aKeyMap = DHCoder.initKey();
        String aPublicKey = DHCoder.getPublicKey(aKeyMap);
        String aPrivateKey = DHCoder.getPrivateKey(aKeyMap);
 
        System.err.println("甲方公钥:\r" + aPublicKey);
        System.err.println("甲方私钥:\r" + aPrivateKey);
         
        // 由甲方公钥产生本地密钥对儿
        Map<String, Object> bKeyMap = DHCoder.initKey(aPublicKey);
        String bPublicKey = DHCoder.getPublicKey(bKeyMap);
        String bPrivateKey = DHCoder.getPrivateKey(bKeyMap);
         
        System.err.println("乙方公钥:\r" + bPublicKey);
        System.err.println("乙方私钥:\r" + bPrivateKey);
         
        String aInput = "abc ";
        System.err.println("原文: " + aInput);
 
        // 由甲方公钥,乙方私钥构建密文
        byte[] aCode = DHCoder.encrypt(aInput.getBytes(), aPublicKey,
                bPrivateKey);
 
        // 由乙方公钥,甲方私钥解密
        byte[] aDecode = DHCoder.decrypt(aCode, bPublicKey, aPrivateKey);
        String aOutput = (new String(aDecode));
 
        System.err.println("解密: " + aOutput);
 
        assertEquals(aInput, aOutput);
 
        System.err.println(" ===============反过来加密解密================== ");
        String bInput = "def ";
        System.err.println("原文: " + bInput);
 
        // 由乙方公钥,甲方私钥构建密文
        byte[] bCode = DHCoder.encrypt(bInput.getBytes(), bPublicKey,
                aPrivateKey);
 
        // 由甲方公钥,乙方私钥解密
        byte[] bDecode = DHCoder.decrypt(bCode, aPublicKey, bPrivateKey);
        String bOutput = (new String(bDecode));
 
        System.err.println("解密: " + bOutput);
 
        assertEquals(bInput, bOutput);
    }
 
}

Saída do console:

甲方公钥:
MIHfMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYXrgHz
W5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpDTWSG
kx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgANDAAJAdAWBVmIzqcko
Ej6qFjLDL2+Y3FPq1iRbnOyOpDj71yKaK1K+FhTv04B0zy4DKcvAASV7/Gv0W+bgqdmffRkqrQ==

甲方私钥:
MIHRAgEAMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYX
rgHzW5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpD
TWSGkx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgAQyAjACJRfy1LyR
eHyD+4Hfb+xR0uoIGR1oL9i9Nk6g2AAuaDPgEVWHn+QXID13yL/uDos=

乙方公钥:
MIHfMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYXrgHz
W5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpDTWSG
kx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgANDAAJAVEYSfBA+I9nr
dWw3OBv475C+eBrWBBYqt0m6/eu4ptuDQHwV4MmUtKAC2wc2nNrdb1wmBhY1X8RnWkJ1XmdDbQ==

乙方私钥:
MIHSAgEAMIGXBgkqhkiG9w0BAwEwgYkCQQD8poLOjhLKuibvzPcRDlJtsHiwXt7LzR60ogjzrhYX
rgHzW5Gkfm32NBPF4S7QiZvNEyrNUNmRUb3EPuc3WS4XAkBnhHGyepz0TukaScUUfbGpqvJE8FpD
TWSGkx0tFCcbnjUDC3H9c9oXkGmzLik1Yw4cIGI1TQ2iCmxBblC+eUykAgIBgAQzAjEAqaZiCdXp
2iNpdBlHRaO9ir70wo2n32xNlIzIX19VLSPCDdeUWkgRv4CEj/8k+/yd

原文: abc 
解密: abc 
 ===============反过来加密解密================== 
原文: def 
解密: def

Como disse, após obter a chave pública da outra parte, ambas as partes podem criptografar os dados enviados à outra parte, e ao mesmo tempo descriptografar os dados recebidos, atingindo o objetivo de comunicação de segurança de dados!

A seguir apresentamos a assinatura digital DSA, outra implementação de criptografia assimétrica.
DSA
O algoritmo de assinatura digital DSA é uma variante dos algoritmos de assinatura Schnorr e ElGamal e é considerado DSS (DigitalSignature Standard) pelo NIST dos EUA. Simplificando, este é um método de verificação mais avançado usado como assinatura digital. Não existem apenas chaves públicas, chaves privadas, mas também assinaturas digitais. A criptografia de chave privada gera assinaturas digitais e a chave pública verifica dados e assinaturas. Se os dados e a assinatura não corresponderem, a verificação será considerada falhada! A função da assinatura digital é verificar se os dados não foram modificados durante a transmissão. A assinatura digital é uma atualização da criptografia unidirecional!

  1. Vários algoritmos de criptografia Java
  2. Vários algoritmos de criptografia Java

Através do código java para conseguir o seguinte: classe Coder veja

import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.DSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
 
/**
 * DSA安全编码组件
 * 
 * @author 梁栋
 * @version 1.0
 * @since 1.0
 */
public abstract class DSACoder extends Coder {
    
    
 
    public static final String ALGORITHM = "DSA";
 
    /**
     * 默认密钥字节数
     * 
     * <pre>
     * DSA 
     * Default Keysize 1024  
     * Keysize must be a multiple of 64, ranging from 512 to 1024 (inclusive).
     * </pre>
     */
    private static final int KEY_SIZE = 1024;
 
    /**
     * 默认种子
     */
    private static final String DEFAULT_SEED = "0f22507a10bbddd07d8a3082122966e3";
 
    private static final String PUBLIC_KEY = "DSAPublicKey";
    private static final String PRIVATE_KEY = "DSAPrivateKey";
 
    /**
     * 用私钥对信息生成数字签名
     * 
     * @param data
     *            加密数据
     * @param privateKey
     *            私钥
     * 
     * @return
     * @throws Exception
     */
    public static String sign(byte[] data, String privateKey) throws Exception {
    
    
        // 解密由base64编码的私钥
        byte[] keyBytes = decryptBASE64(privateKey);
 
        // 构造PKCS8EncodedKeySpec对象
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
 
        // KEY_ALGORITHM 指定的加密算法
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
 
        // 取私钥匙对象
        PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
 
        // 用私钥对信息生成数字签名
        Signature signature = Signature.getInstance(keyFactory.getAlgorithm());
        signature.initSign(priKey);
        signature.update(data);
 
        return encryptBASE64(signature.sign());
    }
 
    /**
     * 校验数字签名
     * 
     * @param data
     *            加密数据
     * @param publicKey
     *            公钥
     * @param sign
     *            数字签名
     * 
     * @return 校验成功返回true 失败返回false
     * @throws Exception
     * 
     */
    public static boolean verify(byte[] data, String publicKey, String sign)
            throws Exception {
    
    
 
        // 解密由base64编码的公钥
        byte[] keyBytes = decryptBASE64(publicKey);
 
        // 构造X509EncodedKeySpec对象
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
 
        // ALGORITHM 指定的加密算法
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
 
        // 取公钥匙对象
        PublicKey pubKey = keyFactory.generatePublic(keySpec);
 
        Signature signature = Signature.getInstance(keyFactory.getAlgorithm());
        signature.initVerify(pubKey);
        signature.update(data);
 
        // 验证签名是否正常
        return signature.verify(decryptBASE64(sign));
    }
 
    /**
     * 生成密钥
     * 
     * @param seed
     *            种子
     * @return 密钥对象
     * @throws Exception
     */
    public static Map<String, Object> initKey(String seed) throws Exception {
    
    
        KeyPairGenerator keygen = KeyPairGenerator.getInstance(ALGORITHM);
        // 初始化随机产生器
        SecureRandom secureRandom = new SecureRandom();
        secureRandom.setSeed(seed.getBytes());
        keygen.initialize(KEY_SIZE, secureRandom);
 
        KeyPair keys = keygen.genKeyPair();
 
        DSAPublicKey publicKey = (DSAPublicKey) keys.getPublic();
        DSAPrivateKey privateKey = (DSAPrivateKey) keys.getPrivate();
 
        Map<String, Object> map = new HashMap<String, Object>(2);
        map.put(PUBLIC_KEY, publicKey);
        map.put(PRIVATE_KEY, privateKey);
 
        return map;
    }
 
    /**
     * 默认生成密钥
     * 
     * @return 密钥对象
     * @throws Exception
     */
    public static Map<String, Object> initKey() throws Exception {
    
    
        return initKey(DEFAULT_SEED);
    }
 
    /**
     * 取得私钥
     * 
     * @param keyMap
     * @return
     * @throws Exception
     */
    public static String getPrivateKey(Map<String, Object> keyMap)
            throws Exception {
    
    
        Key key = (Key) keyMap.get(PRIVATE_KEY);
 
        return encryptBASE64(key.getEncoded());
    }
 
    /**
     * 取得公钥
     * 
     * @param keyMap
     * @return
     * @throws Exception
     */
    public static String getPublicKey(Map<String, Object> keyMap)
            throws Exception {
    
    
        Key key = (Key) keyMap.get(PUBLIC_KEY);
 
        return encryptBASE64(key.getEncoded());
    }
}

Dê outra aula de teste:

import static org.junit.Assert.*;
 
import java.util.Map;
 
import org.junit.Test;
 
/**
 * 
 * @author 梁栋
 * @version 1.0
 * @since 1.0
 */
public class DSACoderTest {
    
    
 
    @Test
    public void test() throws Exception {
    
    
        String inputStr = "abc";
        byte[] data = inputStr.getBytes();
 
        // 构建密钥
        Map<String, Object> keyMap = DSACoder.initKey();
 
        // 获得密钥
        String publicKey = DSACoder.getPublicKey(keyMap);
        String privateKey = DSACoder.getPrivateKey(keyMap);
 
        System.err.println("公钥:\r" + publicKey);
        System.err.println("私钥:\r" + privateKey);
 
        // 产生签名
        String sign = DSACoder.sign(data, privateKey);
        System.err.println("签名:\r" + sign);
 
        // 验证签名
        boolean status = DSACoder.verify(data, publicKey, sign);
        System.err.println("状态:\r" + status);
        assertTrue(status);
 
    }
 
}

Saída do console:

公钥:
MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZp
RV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fn
xqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuE
C/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJ
FnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImo
g9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGAIu4RUlcQLp49PI0MrbssOY+3uySVnp0TULSv
5T4VaHoKzsLHgGTrwOvsGA+V3yCNl2WDu3D84bSLF7liTWgOj+SMOEaPk4VyRTlLXZWGPsf1Mfd9
21XAbMeVyKDSHHVGbMjBScajf3bXooYQMlyoHiOt/WrCo+mv7efstMM0PGo=

私钥:
MIIBTAIBADCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2
USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4
O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmC
ouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCB
gLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhR
kImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoEFwIVAIegLUtmm2oQKQJTOiLugHTSjl/q

签名:
MC0CFQCMg0J/uZmF8GuRpr3TNq48w60nDwIUJCyYNah+HtbU6NcQfy8Ac6LeLQs=

状态:
true

Observe que se o status for verdadeiro, a verificação foi bem-sucedida!

ECC
ECC-Elliptic Curves Cryptography, criptografia de curva elíptica, é um sistema que fornece a maior força de criptografia por bit entre os sistemas de chave pública conhecidos. Ele desempenha um papel importante na proteção de registro de software, e números de série gerais geralmente são gerados por esse algoritmo.
Quando comecei a resolver "Tecnologia de criptografia Java (2)", já havia começado a estudar ECC, mas há muito poucos materiais sobre a implementação de algoritmos ECC em Java, sejam materiais nacionais ou estrangeiros, sejam oficiais ou para a explicação não oficial, há apenas uma resposta no final - o algoritmo ECC é suportado após jdk1.5 e atualmente apenas a geração e análise da chave podem ser concluídas. Se você deseja implementar o algoritmo ECC, você precisa chamar o hardware para completar a criptografia/descriptografia (o algoritmo ECC consome muitos recursos e se você simplesmente usar a CPU para criptografia/descriptografia, a eficiência é baixa), envolvendo o campo do Java Card, PKCS#11. Na verdade, a configuração do PKCS#11 é muito simples, mas por falta de equipamento de hardware, não posso tentar!

No entanto, ainda forneço o código de implementação Java correspondente para sua referência.

Através do código java para conseguir o seguinte: classe Coder veja

import java.math.BigInteger;
import java.security.Key;
import java.security.KeyFactory;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECFieldF2m;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.ECPrivateKeySpec;
import java.security.spec.ECPublicKeySpec;
import java.security.spec.EllipticCurve;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
 
import javax.crypto.Cipher;
import javax.crypto.NullCipher;
 
import sun.security.ec.ECKeyFactory;
import sun.security.ec.ECPrivateKeyImpl;
import sun.security.ec.ECPublicKeyImpl;
 
/**
 * ECC安全编码组件
 * 
 * @author 梁栋
 * @version 1.0
 * @since 1.0
 */
public abstract class ECCCoder extends Coder {
    
    
 
    public static final String ALGORITHM = "EC";
    private static final String PUBLIC_KEY = "ECCPublicKey";
    private static final String PRIVATE_KEY = "ECCPrivateKey";
 
    /**
     * 解密<br>
     * 用私钥解密
     * 
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decrypt(byte[] data, String key) throws Exception {
    
    
        // 对密钥解密
        byte[] keyBytes = decryptBASE64(key);
 
        // 取得私钥
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = ECKeyFactory.INSTANCE;
 
        ECPrivateKey priKey = (ECPrivateKey) keyFactory
                .generatePrivate(pkcs8KeySpec);
 
        ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(priKey.getS(),
                priKey.getParams());
 
        // 对数据解密
        // TODO Chipher不支持EC算法 未能实现
        Cipher cipher = new NullCipher();
        // Cipher.getInstance(ALGORITHM, keyFactory.getProvider());
        cipher.init(Cipher.DECRYPT_MODE, priKey, ecPrivateKeySpec.getParams());
 
        return cipher.doFinal(data);
    }
 
    /**
     * 加密<br>
     * 用公钥加密
     * 
     * @param data
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static byte[] encrypt(byte[] data, String privateKey)
            throws Exception {
    
    
        // 对公钥解密
        byte[] keyBytes = decryptBASE64(privateKey);
 
        // 取得公钥
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = ECKeyFactory.INSTANCE;
 
        ECPublicKey pubKey = (ECPublicKey) keyFactory
                .generatePublic(x509KeySpec);
 
        ECPublicKeySpec ecPublicKeySpec = new ECPublicKeySpec(pubKey.getW(),
                pubKey.getParams());
 
        // 对数据加密
        // TODO Chipher不支持EC算法 未能实现
        Cipher cipher = new NullCipher();
        // Cipher.getInstance(ALGORITHM, keyFactory.getProvider());
        cipher.init(Cipher.ENCRYPT_MODE, pubKey, ecPublicKeySpec.getParams());
 
        return cipher.doFinal(data);
    }
 
    /**
     * 取得私钥
     * 
     * @param keyMap
     * @return
     * @throws Exception
     */
    public static String getPrivateKey(Map<String, Object> keyMap)
            throws Exception {
    
    
        Key key = (Key) keyMap.get(PRIVATE_KEY);
 
        return encryptBASE64(key.getEncoded());
    }
 
    /**
     * 取得公钥
     * 
     * @param keyMap
     * @return
     * @throws Exception
     */
    public static String getPublicKey(Map<String, Object> keyMap)
            throws Exception {
    
    
        Key key = (Key) keyMap.get(PUBLIC_KEY);
 
        return encryptBASE64(key.getEncoded());
    }
 
    /**
     * 初始化密钥
     * 
     * @return
     * @throws Exception
     */
    public static Map<String, Object> initKey() throws Exception {
    
    
        BigInteger x1 = new BigInteger(
                "2fe13c0537bbc11acaa07d793de4e6d5e5c94eee8", 16);
        BigInteger x2 = new BigInteger(
                "289070fb05d38ff58321f2e800536d538ccdaa3d9", 16);
 
        ECPoint g = new ECPoint(x1, x2);
 
        // the order of generator
        BigInteger n = new BigInteger(
                "5846006549323611672814741753598448348329118574063", 10);
        // the cofactor
        int h = 2;
        int m = 163;
        int[] ks = {
    
     7, 6, 3 };
        ECFieldF2m ecField = new ECFieldF2m(m, ks);
        // y^2+xy=x^3+x^2+1
        BigInteger a = new BigInteger("1", 2);
        BigInteger b = new BigInteger("1", 2);
 
        EllipticCurve ellipticCurve = new EllipticCurve(ecField, a, b);
 
        ECParameterSpec ecParameterSpec = new ECParameterSpec(ellipticCurve, g,
                n, h);
        // 公钥
        ECPublicKey publicKey = new ECPublicKeyImpl(g, ecParameterSpec);
 
        BigInteger s = new BigInteger(
                "1234006549323611672814741753598448348329118574063", 10);
        // 私钥
        ECPrivateKey privateKey = new ECPrivateKeyImpl(s, ecParameterSpec);
 
        Map<String, Object> keyMap = new HashMap<String, Object>(2);
 
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
 
        return keyMap;
    }
 
}

Preste atenção ao conteúdo TODO no código acima e lembre-o novamente de que o Chipher não oferece suporte ao algoritmo EC e o código acima é apenas para referência. Chipher, Signature, KeyPairGenerator, KeyAgreement e SecretKey não suportam o algoritmo EC. Para garantir que o programa possa ser executado normalmente, utilizamos a classe NullCipher, o programa de verificação.

Forneça uma classe de teste como de costume:

import static org.junit.Assert.*;
 
import java.math.BigInteger;
import java.security.spec.ECFieldF2m;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.ECPrivateKeySpec;
import java.security.spec.ECPublicKeySpec;
import java.security.spec.EllipticCurve;
import java.util.Map;
 
import org.junit.Test;
 
/**
 * 
 * @author 梁栋
 * @version 1.0
 * @since 1.0
 */
public class ECCCoderTest {
    
    
 
    @Test
    public void test() throws Exception {
    
    
        String inputStr = "abc";
        byte[] data = inputStr.getBytes();
 
        Map<String, Object> keyMap = ECCCoder.initKey();
 
        String publicKey = ECCCoder.getPublicKey(keyMap);
        String privateKey = ECCCoder.getPrivateKey(keyMap);
        System.err.println("公钥: \n" + publicKey);
        System.err.println("私钥: \n" + privateKey);
 
        byte[] encodedData = ECCCoder.encrypt(data, publicKey);
 
        byte[] decodedData = ECCCoder.decrypt(encodedData, privateKey);
 
        String outputStr = new String(decodedData);
        System.err.println("加密前: " + inputStr + "\n\r" + "解密后: " + outputStr);
        assertEquals(inputStr, outputStr);
    }
}

Saída do console:

公钥: 
MEAwEAYHKoZIzj0CAQYFK4EEAAEDLAAEAv4TwFN7vBGsqgfXk95ObV5clO7oAokHD7BdOP9YMh8u
gAU21TjM2qPZ

私钥: 
MDICAQAwEAYHKoZIzj0CAQYFK4EEAAEEGzAZAgEBBBTYJsR3BN7TFw7JHcAHFkwNmfil7w==

加密前: abc

解密后: abc

O conteúdo principal deste artigo é a implementação do sistema de certificados Java.

Antes de construir a implementação do código Java, precisamos concluir a produção do certificado.
1. Gere o arquivo keyStroe
Execute o seguinte comando na linha de comando:

keytool -genkey -validity 36000 -alias www.zlex.org -keyalg RSA -keystore d:\zlex.keystore

Entre eles
, -genkey significa gerar uma chave
-validity especifica o período de validade do certificado, aqui está 36.000 dias
-alias especifica o alias, aqui está www.zlex.org
-keyalg especifica o algoritmo, aqui está RSA
-keystore especifica o local de armazenamento, aqui está d:\zlex.keystore

A senha que uso aqui é 123456

Saída do console:

输入keystore密码:
再次输入新密码:
您的名字与姓氏是什么?
  [Unknown]:  www.zlex.org
您的组织单位名称是什么?
  [Unknown]:  zlex
您的组织名称是什么?
  [Unknown]:  zlex
您所在的城市或区域名称是什么?
  [Unknown]BJ
您所在的州或省份名称是什么?
  [Unknown]BJ
该单位的两字母国家代码是什么
  [Unknown]CN
CN=www.zlex.org, OU=zlex, O=zlex, L=BJ, ST=BJ, C=CN 正确吗?
  []Y

输入<tomcat>的主密码
        (如果和 keystore 密码相同,按回车):
再次输入新密码:

Neste momento, um arquivo zlex.keystore será gerado na unidade D.

2. Gerar um certificado autoassinado.
Não basta ter um arquivo keyStore, também é necessário um arquivo de certificado. O certificado é o certificado de chave pública fornecido diretamente ao mundo exterior.
Exporte o certificado:

keytool -export -keystore d:\zlex.keystore -alias www.zlex.org -file d:\zlex.cer -rfc

Onde
-export é especificado como a operação de exportação
-keystore especifica o arquivo keystore
-alias especifica o alias no arquivo keystore exportado
-file aponta para o caminho de exportação
-rfc é gerado em formato de texto, ou seja, gerado na codificação BASE64
A senha aqui é 123456

Saída do console:

输入keystore密码:
保存在文件中的认证 <d:\zlex.cer>

Claro que o usuário precisa importar o certificado!
A construção do sistema de login único CAS pode ser concluída por meio de certificados autoassinados!

Ok, o trabalho preparatório está concluído e a implementação do Java começa!

Através do código java para conseguir o seguinte: classe Coder veja

import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Date;
 
import javax.crypto.Cipher;
 
/**
 * 证书组件
 * 
 * @author 梁栋
 * @version 1.0
 * @since 1.0
 */
public abstract class CertificateCoder extends Coder {
    
    
 
 
    /**
     * Java密钥库(Java Key Store,JKS)KEY_STORE
     */
    public static final String KEY_STORE = "JKS";
 
    public static final String X509 = "X.509";
 
    /**
     * 由KeyStore获得私钥
     * 
     * @param keyStorePath
     * @param alias
     * @param password
     * @return
     * @throws Exception
     */
    private static PrivateKey getPrivateKey(String keyStorePath, String alias,
            String password) throws Exception {
    
    
        KeyStore ks = getKeyStore(keyStorePath, password);
        PrivateKey key = (PrivateKey) ks.getKey(alias, password.toCharArray());
        return key;
    }
 
    /**
     * 由Certificate获得公钥
     * 
     * @param certificatePath
     * @return
     * @throws Exception
     */
    private static PublicKey getPublicKey(String certificatePath)
            throws Exception {
    
    
        Certificate certificate = getCertificate(certificatePath);
        PublicKey key = certificate.getPublicKey();
        return key;
    }
 
    /**
     * 获得Certificate
     * 
     * @param certificatePath
     * @return
     * @throws Exception
     */
    private static Certificate getCertificate(String certificatePath)
            throws Exception {
    
    
        CertificateFactory certificateFactory = CertificateFactory
                .getInstance(X509);
        FileInputStream in = new FileInputStream(certificatePath);
 
        Certificate certificate = certificateFactory.generateCertificate(in);
        in.close();
 
        return certificate;
    }
 
    /**
     * 获得Certificate
     * 
     * @param keyStorePath
     * @param alias
     * @param password
     * @return
     * @throws Exception
     */
    private static Certificate getCertificate(String keyStorePath,
            String alias, String password) throws Exception {
    
    
        KeyStore ks = getKeyStore(keyStorePath, password);
        Certificate certificate = ks.getCertificate(alias);
 
        return certificate;
    }
 
    /**
     * 获得KeyStore
     * 
     * @param keyStorePath
     * @param password
     * @return
     * @throws Exception
     */
    private static KeyStore getKeyStore(String keyStorePath, String password)
            throws Exception {
    
    
        FileInputStream is = new FileInputStream(keyStorePath);
        KeyStore ks = KeyStore.getInstance(KEY_STORE);
        ks.load(is, password.toCharArray());
        is.close();
        return ks;
    }
 
    /**
     * 私钥加密
     * 
     * @param data
     * @param keyStorePath
     * @param alias
     * @param password
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPrivateKey(byte[] data, String keyStorePath,
            String alias, String password) throws Exception {
    
    
        // 取得私钥
        PrivateKey privateKey = getPrivateKey(keyStorePath, alias, password);
 
        // 对数据加密
        Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
 
        return cipher.doFinal(data);
 
    }
 
    /**
     * 私钥解密
     * 
     * @param data
     * @param keyStorePath
     * @param alias
     * @param password
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPrivateKey(byte[] data, String keyStorePath,
            String alias, String password) throws Exception {
    
    
        // 取得私钥
        PrivateKey privateKey = getPrivateKey(keyStorePath, alias, password);
 
        // 对数据加密
        Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
 
        return cipher.doFinal(data);
 
    }
 
    /**
     * 公钥加密
     * 
     * @param data
     * @param certificatePath
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPublicKey(byte[] data, String certificatePath)
            throws Exception {
    
    
 
        // 取得公钥
        PublicKey publicKey = getPublicKey(certificatePath);
        // 对数据加密
        Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
 
        return cipher.doFinal(data);
 
    }
 
    /**
     * 公钥解密
     * 
     * @param data
     * @param certificatePath
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPublicKey(byte[] data, String certificatePath)
            throws Exception {
    
    
        // 取得公钥
        PublicKey publicKey = getPublicKey(certificatePath);
 
        // 对数据加密
        Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
 
        return cipher.doFinal(data);
 
    }
 
    /**
     * 验证Certificate
     * 
     * @param certificatePath
     * @return
     */
    public static boolean verifyCertificate(String certificatePath) {
    
    
        return verifyCertificate(new Date(), certificatePath);
    }
 
    /**
     * 验证Certificate是否过期或无效
     * 
     * @param date
     * @param certificatePath
     * @return
     */
    public static boolean verifyCertificate(Date date, String certificatePath) {
    
    
        boolean status = true;
        try {
    
    
            // 取得证书
            Certificate certificate = getCertificate(certificatePath);
            // 验证证书是否过期或无效
            status = verifyCertificate(date, certificate);
        } catch (Exception e) {
    
    
            status = false;
        }
        return status;
    }
 
    /**
     * 验证证书是否过期或无效
     * 
     * @param date
     * @param certificate
     * @return
     */
    private static boolean verifyCertificate(Date date, Certificate certificate) {
    
    
        boolean status = true;
        try {
    
    
            X509Certificate x509Certificate = (X509Certificate) certificate;
            x509Certificate.checkValidity(date);
        } catch (Exception e) {
    
    
            status = false;
        }
        return status;
    }
 
    /**
     * 签名
     * 
     * @param keyStorePath
     * @param alias
     * @param password
     * 
     * @return
     * @throws Exception
     */
    public static String sign(byte[] sign, String keyStorePath, String alias,
            String password) throws Exception {
    
    
        // 获得证书
        X509Certificate x509Certificate = (X509Certificate) getCertificate(
                keyStorePath, alias, password);
        // 获取私钥
        KeyStore ks = getKeyStore(keyStorePath, password);
        // 取得私钥
        PrivateKey privateKey = (PrivateKey) ks.getKey(alias, password
                .toCharArray());
 
        // 构建签名
        Signature signature = Signature.getInstance(x509Certificate
                .getSigAlgName());
        signature.initSign(privateKey);
        signature.update(sign);
        return encryptBASE64(signature.sign());
    }
 
    /**
     * 验证签名
     * 
     * @param data
     * @param sign
     * @param certificatePath
     * @return
     * @throws Exception
     */
    public static boolean verify(byte[] data, String sign,
            String certificatePath) throws Exception {
    
    
        // 获得证书
        X509Certificate x509Certificate = (X509Certificate) getCertificate(certificatePath);
        // 获得公钥
        PublicKey publicKey = x509Certificate.getPublicKey();
        // 构建签名
        Signature signature = Signature.getInstance(x509Certificate
                .getSigAlgName());
        signature.initVerify(publicKey);
        signature.update(data);
 
        return signature.verify(decryptBASE64(sign));
 
    }
 
    /**
     * 验证Certificate
     * 
     * @param keyStorePath
     * @param alias
     * @param password
     * @return
     */
    public static boolean verifyCertificate(Date date, String keyStorePath,
            String alias, String password) {
    
    
        boolean status = true;
        try {
    
    
            Certificate certificate = getCertificate(keyStorePath, alias,
                    password);
            status = verifyCertificate(date, certificate);
        } catch (Exception e) {
    
    
            status = false;
        }
        return status;
    }
 
    /**
     * 验证Certificate
     * 
     * @param keyStorePath
     * @param alias
     * @param password
     * @return
     */
    public static boolean verifyCertificate(String keyStorePath, String alias,
            String password) {
    
    
        return verifyCertificate(new Date(), keyStorePath, alias, password);
    }
}

Dê outra aula de teste:

import static org.junit.Assert.*;
 
import org.junit.Test;
 
/**
 * 
 * @author 梁栋
 * @version 1.0
 * @since 1.0
 */
public class CertificateCoderTest {
    
    
    private String password = "123456";
    private String alias = "www.zlex.org";
    private String certificatePath = "d:/zlex.cer";
    private String keyStorePath = "d:/zlex.keystore";
 
    @Test
    public void test() throws Exception {
    
    
        System.err.println("公钥加密——私钥解密");
        String inputStr = "Ceritifcate";
        byte[] data = inputStr.getBytes();
 
        byte[] encrypt = CertificateCoder.encryptByPublicKey(data,
                certificatePath);
 
        byte[] decrypt = CertificateCoder.decryptByPrivateKey(encrypt,
                keyStorePath, alias, password);
        String outputStr = new String(decrypt);
 
        System.err.println("加密前: " + inputStr + "\n\r" + "解密后: " + outputStr);
 
        // 验证数据一致
        assertArrayEquals(data, decrypt);
 
        // 验证证书有效
        assertTrue(CertificateCoder.verifyCertificate(certificatePath));
 
    }
 
    @Test
    public void testSign() throws Exception {
    
    
        System.err.println("私钥加密——公钥解密");
 
        String inputStr = "sign";
        byte[] data = inputStr.getBytes();
 
        byte[] encodedData = CertificateCoder.encryptByPrivateKey(data,
                keyStorePath, alias, password);
 
        byte[] decodedData = CertificateCoder.decryptByPublicKey(encodedData,
                certificatePath);
 
        String outputStr = new String(decodedData);
        System.err.println("加密前: " + inputStr + "\n\r" + "解密后: " + outputStr);
        assertEquals(inputStr, outputStr);
 
        System.err.println("私钥签名——公钥验证签名");
        // 产生签名
        String sign = CertificateCoder.sign(encodedData, keyStorePath, alias,
                password);
        System.err.println("签名:\r" + sign);
 
        // 验证签名
        boolean status = CertificateCoder.verify(encodedData, sign,
                certificatePath);
        System.err.println("状态:\r" + status);
        assertTrue(status);
 
    }
}

Saída do console:

公钥加密——私钥解密
加密前: Ceritificate

解密后: Ceritificate

私钥加密——公钥解密
加密前: sign

解密后: sign
私钥签名——公钥验证签名
签名:
pqBn5m6PJlfOjH0A6U2o2mUmBsfgyEY1NWCbiyA/I5Gc3gaVNVIdj/zkGNZRqTjhf3+J9a9z9EI7
6F2eWYd7punHx5oh6hfNgcKbVb52EfItl4QEN+djbXiPynn07+Lbg1NOjULnpEd6ZhLP1YwrEAuM
OfvX0e7/wplxLbySaKQ=

状态:
true

Isso completa o sistema de verificação de certificado!

Da mesma forma, podemos assinar código – assinatura de código!
A assinatura do código pode ser feita através da ferramenta JarSigner.
Aqui assinamos o código tools.jar, o comando é o seguinte:

jarsigner -storetype jks -keystore zlex.keystore -verbose tools.jar www.zlex.org

Saída do console:

输入密钥库的口令短语:
 正在更新: META-INF/WWW_ZLEX.SF
 正在更新: META-INF/WWW_ZLEX.RSA
  正在签名: org/zlex/security/Security.class
  正在签名: org/zlex/tool/Main$1.class
  正在签名: org/zlex/tool/Main$2.class
  正在签名: org/zlex/tool/Main.class

警告:
签名者证书将在六个月内过期。

Neste ponto, podemos verificar o jar assinado!
Verifique tools.jar, o comando é o seguinte:

jarsigner -verify -verbose -certs tools.jar

Saída do console:

         402 Sat Jun 20 16:25:14 CST 2009 META-INF/MANIFEST.MF
         532 Sat Jun 20 16:25:14 CST 2009 META-INF/WWW_ZLEX.SF
         889 Sat Jun 20 16:25:14 CST 2009 META-INF/WWW_ZLEX.RSA
sm       590 Wed Dec 10 13:03:42 CST 2008 org/zlex/security/Security.class

      X.509, CN=www.zlex.org, OU=zlex, O=zlex, L=BJ, ST=BJ, C=CN
      [证书将在 09-9-18 下午3:27 到期]

sm       705 Tue Dec 16 18:00:56 CST 2008 org/zlex/tool/Main$1.class

      X.509, CN=www.zlex.org, OU=zlex, O=zlex, L=BJ, ST=BJ, C=CN
      [证书将在 09-9-18 下午3:27 到期]

sm       779 Tue Dec 16 18:00:56 CST 2008 org/zlex/tool/Main$2.class

      X.509, CN=www.zlex.org, OU=zlex, O=zlex, L=BJ, ST=BJ, C=CN
      [证书将在 09-9-18 下午3:27 到期]

sm     12672 Tue Dec 16 18:00:56 CST 2008 org/zlex/tool/Main.class

      X.509, CN=www.zlex.org, OU=zlex, O=zlex, L=BJ, ST=BJ, C=CN
      [证书将在 09-9-18 下午3:27 到期]


  s = 已验证签名
  m = 在清单中列出条目
  k = 在密钥库中至少找到了一个证书
  i = 在身份作用域内至少找到了一个证书

jar 已验证。

警告:
此 jar 包含签名者证书将在六个月内过期的条目。

O objetivo da certificação de assinatura de código é principalmente verificar o software lançado e oferece suporte a arquivos Sun Java .jar (Java Applet) (J2SE) e arquivos J2ME MIDlet Suite.

Em, simulamos uma comunicação segura através de uma rede baseada em criptografia assimétrica RSA. Agora vamos dar uma olhada mais profunda na comunicação de rede segura existente - SSL. Precisamos construir um certificado válido emitido pela CA, aqui usamos o certificado autoassinado zlex.cer
gerado acima. Aqui, importamos o certificado para nosso keystore.

keytool -import -alias www.zlex.org -file d:/zlex.cer -keystore d:/zlex.keystore

Entre eles
, -import significa importar
-alias especifica o alias, aqui está www.zlex.org
-file especifica o algoritmo, aqui está d:/zlex.cer
-keystore especifica o local de armazenamento, aqui está d:/zlex.keystore
aqui eu uso a senha 654321

Saída do console:

输入keystore密码:
再次输入新密码:
所有者:CN=www.zlex.org, OU=zlex, O=zlex, L=BJ, ST=BJ, C=CN
签发人:CN=www.zlex.org, OU=zlex, O=zlex, L=BJ, ST=BJ, C=CN
序列号:4a1e48df
有效期: Thu May 28 16:18:39 CST 2009Wed Aug 26 16:18:39 CST 2009
证书指纹:
         MD5:19:CA:E6:36:E2:DF:AD:96:31:97:2F:A9:AD:FC:37:6A
         SHA1:49:88:30:59:29:45:F1:69:CA:97:A9:6D:8A:CF:08:D2:C3:D5:C0:C4
         签名算法名称:SHA1withRSA
         版本: 3
信任这个认证? []:  y
认证已添加至keystore中

OK, os preparativos mais complicados estão feitos.
A seguir, localizamos o nome de domínio www.zlex.org nesta máquina. Abra o arquivo C:\Windows\System32\drivers\etc\hosts e vincule www.zlex.org a esta máquina. Anexe 127.0.0.1 www.zlex.org ao final do arquivo . Agora visite http://www.zlex.org através da barra de endereço , ou através do comando ping , se a máquina puder ser localizada, o mapeamento do nome de domínio está feito.
Agora, configure o Tomcat. Primeiro copie zlex.keystore para o diretório conf do Tomcat e, em seguida, configure server.xml . Adicione o seguinte conteúdo ao arquivo de configuração

<Connector
			SSLEnabled="true"
			URIEncoding="UTF-8"
			clientAuth="false"
			keystoreFile="conf/zlex.keystore"
			keystorePass="123456"
			maxThreads="150"
			port="443"
			protocol="HTTP/1.1"
			scheme="https"
			secure="true"
			sslProtocol="TLS" />

Observe que clientAuth="false" é definido como false durante a fase de teste e true é recomendado para uso formal . Agora inicie o Tomcat, visite https://www.zlex.org/. Obviamente, o certificado não passou na certificação. Neste momento, você pode optar por instalar o certificado ( o arquivo zlex.cerVários algoritmos de criptografia Java
acima é o certificado), importá-lo como uma autoridade de certificação raiz confiável e reiniciar o navegador novamente (ou seja, outros navegadores são para o nome de domínio www .zlex.org não suporta acesso local), visite https://www.zlex.org/, você verá um pequeno cadeado na barra de endereço , o que significa que a instalação foi bem-sucedida. Todas as operações de rede do navegador já estão sob a proteção do sistema de criptografia e descriptografia RSA. Mas parece que não sentimos isso. Neste momento, muitas pessoas começaram a duvidar, se quisermos fazer manualmente esse acesso https, precisamos implementar todas essas funções do navegador? desnecessário!Vários algoritmos de criptografia Java

Seguindo o conteúdo do artigo anterior, é fornecida a seguinte implementação de código:

import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Date;
 
import javax.crypto.Cipher;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
 
/**
 * 证书组件
 * 
 * @author 梁栋
 * @version 1.0
 * @since 1.0
 */
public abstract class CertificateCoder extends Coder {
    
    
 
    /**
     * Java密钥库(Java Key Store,JKS)KEY_STORE
     */
    public static final String KEY_STORE = "JKS";
 
    public static final String X509 = "X.509";
    public static final String SunX509 = "SunX509";
    public static final String SSL = "SSL";
 
    /**
     * 由KeyStore获得私钥
     * 
     * @param keyStorePath
     * @param alias
     * @param password
     * @return
     * @throws Exception
     */
    private static PrivateKey getPrivateKey(String keyStorePath, String alias,
            String password) throws Exception {
    
    
        KeyStore ks = getKeyStore(keyStorePath, password);
        PrivateKey key = (PrivateKey) ks.getKey(alias, password.toCharArray());
        return key;
    }
 
    /**
     * 由Certificate获得公钥
     * 
     * @param certificatePath
     * @return
     * @throws Exception
     */
    private static PublicKey getPublicKey(String certificatePath)
            throws Exception {
    
    
        Certificate certificate = getCertificate(certificatePath);
        PublicKey key = certificate.getPublicKey();
        return key;
    }
 
    /**
     * 获得Certificate
     * 
     * @param certificatePath
     * @return
     * @throws Exception
     */
    private static Certificate getCertificate(String certificatePath)
            throws Exception {
    
    
        CertificateFactory certificateFactory = CertificateFactory
                .getInstance(X509);
        FileInputStream in = new FileInputStream(certificatePath);
 
        Certificate certificate = certificateFactory.generateCertificate(in);
        in.close();
 
        return certificate;
    }
 
    /**
     * 获得Certificate
     * 
     * @param keyStorePath
     * @param alias
     * @param password
     * @return
     * @throws Exception
     */
    private static Certificate getCertificate(String keyStorePath,
            String alias, String password) throws Exception {
    
    
        KeyStore ks = getKeyStore(keyStorePath, password);
        Certificate certificate = ks.getCertificate(alias);
 
        return certificate;
    }
 
    /**
     * 获得KeyStore
     * 
     * @param keyStorePath
     * @param password
     * @return
     * @throws Exception
     */
    private static KeyStore getKeyStore(String keyStorePath, String password)
            throws Exception {
    
    
        FileInputStream is = new FileInputStream(keyStorePath);
        KeyStore ks = KeyStore.getInstance(KEY_STORE);
        ks.load(is, password.toCharArray());
        is.close();
        return ks;
    }
 
    /**
     * 私钥加密
     * 
     * @param data
     * @param keyStorePath
     * @param alias
     * @param password
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPrivateKey(byte[] data, String keyStorePath,
            String alias, String password) throws Exception {
    
    
        // 取得私钥
        PrivateKey privateKey = getPrivateKey(keyStorePath, alias, password);
 
        // 对数据加密
        Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
 
        return cipher.doFinal(data);
 
    }
 
    /**
     * 私钥解密
     * 
     * @param data
     * @param keyStorePath
     * @param alias
     * @param password
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPrivateKey(byte[] data, String keyStorePath,
            String alias, String password) throws Exception {
    
    
        // 取得私钥
        PrivateKey privateKey = getPrivateKey(keyStorePath, alias, password);
 
        // 对数据加密
        Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
 
        return cipher.doFinal(data);
 
    }
 
    /**
     * 公钥加密
     * 
     * @param data
     * @param certificatePath
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPublicKey(byte[] data, String certificatePath)
            throws Exception {
    
    
 
        // 取得公钥
        PublicKey publicKey = getPublicKey(certificatePath);
        // 对数据加密
        Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
 
        return cipher.doFinal(data);
 
    }
 
    /**
     * 公钥解密
     * 
     * @param data
     * @param certificatePath
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPublicKey(byte[] data, String certificatePath)
            throws Exception {
    
    
        // 取得公钥
        PublicKey publicKey = getPublicKey(certificatePath);
 
        // 对数据加密
        Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
 
        return cipher.doFinal(data);
 
    }
 
    /**
     * 验证Certificate
     * 
     * @param certificatePath
     * @return
     */
    public static boolean verifyCertificate(String certificatePath) {
    
    
        return verifyCertificate(new Date(), certificatePath);
    }
 
    /**
     * 验证Certificate是否过期或无效
     * 
     * @param date
     * @param certificatePath
     * @return
     */
    public static boolean verifyCertificate(Date date, String certificatePath) {
    
    
        boolean status = true;
        try {
    
    
            // 取得证书
            Certificate certificate = getCertificate(certificatePath);
            // 验证证书是否过期或无效
            status = verifyCertificate(date, certificate);
        } catch (Exception e) {
    
    
            status = false;
        }
        return status;
    }
 
    /**
     * 验证证书是否过期或无效
     * 
     * @param date
     * @param certificate
     * @return
     */
    private static boolean verifyCertificate(Date date, Certificate certificate) {
    
    
        boolean status = true;
        try {
    
    
            X509Certificate x509Certificate = (X509Certificate) certificate;
            x509Certificate.checkValidity(date);
        } catch (Exception e) {
    
    
            status = false;
        }
        return status;
    }
 
    /**
     * 签名
     * 
     * @param keyStorePath
     * @param alias
     * @param password
     * 
     * @return
     * @throws Exception
     */
    public static String sign(byte[] sign, String keyStorePath, String alias,
            String password) throws Exception {
    
    
        // 获得证书
        X509Certificate x509Certificate = (X509Certificate) getCertificate(
                keyStorePath, alias, password);
        // 获取私钥
        KeyStore ks = getKeyStore(keyStorePath, password);
        // 取得私钥
        PrivateKey privateKey = (PrivateKey) ks.getKey(alias, password
                .toCharArray());
 
        // 构建签名
        Signature signature = Signature.getInstance(x509Certificate
                .getSigAlgName());
        signature.initSign(privateKey);
        signature.update(sign);
        return encryptBASE64(signature.sign());
    }
 
    /**
     * 验证签名
     * 
     * @param data
     * @param sign
     * @param certificatePath
     * @return
     * @throws Exception
     */
    public static boolean verify(byte[] data, String sign,
            String certificatePath) throws Exception {
    
    
        // 获得证书
        X509Certificate x509Certificate = (X509Certificate) getCertificate(certificatePath);
        // 获得公钥
        PublicKey publicKey = x509Certificate.getPublicKey();
        // 构建签名
        Signature signature = Signature.getInstance(x509Certificate
                .getSigAlgName());
        signature.initVerify(publicKey);
        signature.update(data);
 
        return signature.verify(decryptBASE64(sign));
 
    }
 
    /**
     * 验证Certificate
     * 
     * @param keyStorePath
     * @param alias
     * @param password
     * @return
     */
    public static boolean verifyCertificate(Date date, String keyStorePath,
            String alias, String password) {
    
    
        boolean status = true;
        try {
    
    
            Certificate certificate = getCertificate(keyStorePath, alias,
                    password);
            status = verifyCertificate(date, certificate);
        } catch (Exception e) {
    
    
            status = false;
        }
        return status;
    }
 
    /**
     * 验证Certificate
     * 
     * @param keyStorePath
     * @param alias
     * @param password
     * @return
     */
    public static boolean verifyCertificate(String keyStorePath, String alias,
            String password) {
    
    
        return verifyCertificate(new Date(), keyStorePath, alias, password);
    }
 
    /**
     * 获得SSLSocektFactory
     * 
     * @param password
     *            密码
     * @param keyStorePath
     *            密钥库路径
     * 
     * @param trustKeyStorePath
     *            信任库路径
     * @return
     * @throws Exception
     */
    private static SSLSocketFactory getSSLSocketFactory(String password,
            String keyStorePath, String trustKeyStorePath) throws Exception {
    
    
        // 初始化密钥库
        KeyManagerFactory keyManagerFactory = KeyManagerFactory
                .getInstance(SunX509);
        KeyStore keyStore = getKeyStore(keyStorePath, password);
        keyManagerFactory.init(keyStore, password.toCharArray());
 
        // 初始化信任库
        TrustManagerFactory trustManagerFactory = TrustManagerFactory
                .getInstance(SunX509);
        KeyStore trustkeyStore = getKeyStore(trustKeyStorePath, password);
        trustManagerFactory.init(trustkeyStore);
 
        // 初始化SSL上下文
        SSLContext ctx = SSLContext.getInstance(SSL);
        ctx.init(keyManagerFactory.getKeyManagers(), trustManagerFactory
                .getTrustManagers(), null);
        SSLSocketFactory sf = ctx.getSocketFactory();
 
        return sf;
    }
 
    /**
     * 为HttpsURLConnection配置SSLSocketFactory
     * 
     * @param conn
     *            HttpsURLConnection
     * @param password
     *            密码
     * @param keyStorePath
     *            密钥库路径
     * 
     * @param trustKeyStorePath
     *            信任库路径
     * @throws Exception
     */
    public static void configSSLSocketFactory(HttpsURLConnection conn,
            String password, String keyStorePath, String trustKeyStorePath)
            throws Exception {
    
    
        conn.setSSLSocketFactory(getSSLSocketFactory(password, keyStorePath,
                trustKeyStorePath));
    }
}

O método configSSLSocketFactory é adicionado para chamadas externas, que configura SSLSocketFactory para HttpsURLConnection. Quando HttpsURLConnection é configurado com SSLSocketFactory, podemos usar HttpURLConnection para operar normalmente por meio de getInputStream e getOutputStream de HttpsURLConnection. Em particular, deve-se observar que antes de SSLSocketFactory ser configurado, o valor obtido por getContentLength() de HttpsURLConnection será sempre **-1**.

Dada a classe de teste correspondente:

import static org.junit.Assert.*;
 
import java.io.DataInputStream;
import java.io.InputStream;
import java.net.URL;
 
import javax.net.ssl.HttpsURLConnection;
 
import org.junit.Test;
 
/**
 * 
 * @author 梁栋
 * @version 1.0
 * @since 1.0
 */
public class CertificateCoderTest {
    
    
    private String password = "123456";
    private String alias = "www.zlex.org";
    private String certificatePath = "d:/zlex.cer";
    private String keyStorePath = "d:/zlex.keystore";
    private String clientKeyStorePath = "d:/zlex-client.keystore";
    private String clientPassword = "654321";
 
    @Test
    public void test() throws Exception {
    
    
        System.err.println("公钥加密——私钥解密");
        String inputStr = "Ceritifcate";
        byte[] data = inputStr.getBytes();
 
        byte[] encrypt = CertificateCoder.encryptByPublicKey(data,
                certificatePath);
 
        byte[] decrypt = CertificateCoder.decryptByPrivateKey(encrypt,
                keyStorePath, alias, password);
        String outputStr = new String(decrypt);
 
        System.err.println("加密前: " + inputStr + "\n\r" + "解密后: " + outputStr);
 
        // 验证数据一致
        assertArrayEquals(data, decrypt);
 
        // 验证证书有效
        assertTrue(CertificateCoder.verifyCertificate(certificatePath));
 
    }
 
    @Test
    public void testSign() throws Exception {
    
    
        System.err.println("私钥加密——公钥解密");
 
        String inputStr = "sign";
        byte[] data = inputStr.getBytes();
 
        byte[] encodedData = CertificateCoder.encryptByPrivateKey(data,
                keyStorePath, alias, password);
 
        byte[] decodedData = CertificateCoder.decryptByPublicKey(encodedData,
                certificatePath);
 
        String outputStr = new String(decodedData);
        System.err.println("加密前: " + inputStr + "\n\r" + "解密后: " + outputStr);
        assertEquals(inputStr, outputStr);
 
        System.err.println("私钥签名——公钥验证签名");
        // 产生签名
        String sign = CertificateCoder.sign(encodedData, keyStorePath, alias,
                password);
        System.err.println("签名:\r" + sign);
 
        // 验证签名
        boolean status = CertificateCoder.verify(encodedData, sign,
                certificatePath);
        System.err.println("状态:\r" + status);
        assertTrue(status);
 
    }
 
    @Test
    public void testHttps() throws Exception {
    
    
        URL url = new URL("https://www.zlex.org/examples/");
        HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
 
        conn.setDoInput(true);
        conn.setDoOutput(true);
 
        CertificateCoder.configSSLSocketFactory(conn, clientPassword,
                clientKeyStorePath, clientKeyStorePath);
 
        InputStream is = conn.getInputStream();
 
        int length = conn.getContentLength();
 
        DataInputStream dis = new DataInputStream(is);
        byte[] data = new byte[length];
        dis.readFully(data);
 
        dis.close();
        System.err.println(new String(data));
        conn.disconnect();
    }
}

Preste atenção ao método testHttps , que é quase igual ao nosso acesso HTTP normal. Vejamos a saída do console:

<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD><TITLE>Apache Tomcat Examples</TITLE>
<META http-equiv=Content-Type content="text/html">
</HEAD>
<BODY>
<P>
<H3>Apache Tomcat Examples</H3>
<P></P>
<ul>
<li><a href="http://javaeye.shaduwang.com/?snowolf/blog/servlets">Servlets examples</a></li>
<li><a href="http://javaeye.shaduwang.com/?snowolf/blog/jsp">JSP Examples</a></li>
</ul>
</BODY></HTML>

Visitar https://www.zlex.org/examples/ diretamente pelo navegador também obterá o conteúdo acima. Ou seja, usando a Parte A como servidor para construir o serviço Tomcat, a Parte B pode acessar o aplicativo SSL protegido da Parte A através do método acima e não precisa considerar problemas específicos de criptografia e descriptografia. A Parte A e a Parte B podem configurar serviços SSL eficazes por meio do tomcat de ambas as partes por meio da configuração correspondente, simplificar a implementação do código acima e concluir a autenticação SSL bidirecional por meio da configuração do certificado!

Fizemos a autenticação usando um certificado autoassinado. Em seguida, usamos uma autoridade de assinatura de CA de terceiros para concluir a assinatura do certificado.
Aqui usamos o certificado ca gratuito de 21 dias fornecido pela thawte para teste.
1. Para indicar o seu nome de domínio neste site, use www.zlex.org como nome de domínio para teste (não use este nome de domínio como endereço de nome de domínio, este nome de domínio é protegido por lei! Por favor, use outro não registrado nomes de domínio!) .
2. Se o nome de domínio for válido, você receberá um e-mail solicitando que visite https://www.thawte.com/cgi/server/try.exe para obter um certificado CA.
3. Recite a criação do keystore.

keytool -genkey -validity 36000 -alias www.zlex.org -keyalg RSA -keystore d:\zlex.keystore

A senha que uso aqui é 123456

Saída do console:

输入keystore密码:
再次输入新密码:
您的名字与姓氏是什么?
  [Unknown]:  www.zlex.org
您的组织单位名称是什么?
  [Unknown]:  zlex
您的组织名称是什么?
  [Unknown]:  zlex
您所在的城市或区域名称是什么?
  [Unknown]BJ
您所在的州或省份名称是什么?
  [Unknown]BJ
该单位的两字母国家代码是什么
  [Unknown]CN
CN=www.zlex.org, OU=zlex, O=zlex, L=BJ, ST=BJ, C=CN 正确吗?
  []Y

输入<tomcat>的主密码
        (如果和 keystore 密码相同,按回车):
再次输入新密码:

4. Use o comando a seguir para exportar o aplicativo de certificado CA de zlex.keystore.

keytool -certreq -alias www.zlex.org -file d:\zlex.csr -keystore d:\zlex.keystore -v

Você obterá o arquivo zlex.csr, que pode ser aberto com o Bloco de Notas, e o conteúdo está no seguinte formato:

-----BEGIN NEW CERTIFICATE REQUEST-----
MIIBnDCCAQUCAQAwXDELMAkGA1UEBhMCQ04xCzAJBgNVBAgTAkJKMQswCQYDVQQHEwJCSjENMAsG
A1UEChMEemxleDENMAsGA1UECxMEemxleDEVMBMGA1UEAxMMd3d3LnpsZXgub3JnMIGfMA0GCSqG
SIb3DQEBAQUAA4GNADCBiQKBgQCR6DXU9Mp+mCKO7cv9JPsj0n1Ec/GpM09qvhpgX3FNad/ZWSDc
vU77YXZSoF9hQp3w1LC+eeKgd2MlVpXTvbVwBNVd2HiQPp37ic6BUUjSaX8LHtCl7l0BIEye9qQ2
j8G0kak7e8ZA0s7nb3Ymq/K8BV7v0MQIdhIc1bifK9ZDewIDAQABoAAwDQYJKoZIhvcNAQEFBQAD
gYEAMA1r2fbZPtNx37U9TRwadCH2TZZecwKJS/hskNm6ryPKIAp9APWwAyj8WJHRBz5SpZM4zmYO
oMCI8BcnY2A4JP+R7/SwXTdH/xcg7NVghd9A2SCgqMpF7KMfc5dE3iygdiPu+UhY200Dvpjx8gmJ
1UbH3+nqMUyCrZgURFslOUY=
-----END NEW CERTIFICATE REQUEST-----

5. Copie o conteúdo do arquivo acima para https://www.thawte.com/cgi/server/try.exe, clique em próximo para obter o conteúdo da resposta, aqui está o formato p7b.
O conteúdo é o seguinte:

-----BEGIN PKCS7-----
MIIF3AYJKoZIhvcNAQcCoIIFzTCCBckCAQExADALBgkqhkiG9w0BBwGgggWxMIID
EDCCAnmgAwIBAgIQA/mx/pKoaB+KGX2hveFU9zANBgkqhkiG9w0BAQUFADCBhzEL
MAkGA1UEBhMCWkExIjAgBgNVBAgTGUZPUiBURVNUSU5HIFBVUlBPU0VTIE9OTFkx
HTAbBgNVBAoTFFRoYXd0ZSBDZXJ0aWZpY2F0aW9uMRcwFQYDVQQLEw5URVNUIFRF
U1QgVEVTVDEcMBoGA1UEAxMTVGhhd3RlIFRlc3QgQ0EgUm9vdDAeFw0wOTA1Mjgw
MDIxMzlaFw0wOTA2MTgwMDIxMzlaMFwxCzAJBgNVBAYTAkNOMQswCQYDVQQIEwJC
SjELMAkGA1UEBxMCQkoxDTALBgNVBAoTBHpsZXgxDTALBgNVBAsTBHpsZXgxFTAT
BgNVBAMTDHd3dy56bGV4Lm9yZzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
keg11PTKfpgiju3L/ST7I9J9RHPxqTNPar4aYF9xTWnf2Vkg3L1O+2F2UqBfYUKd
8NSwvnnioHdjJVaV0721cATVXdh4kD6d+4nOgVFI0ml/Cx7Qpe5dASBMnvakNo/B
tJGpO3vGQNLO5292JqvyvAVe79DECHYSHNW4nyvWQ3sCAwEAAaOBpjCBozAMBgNV
HRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBABgNVHR8E
OTA3MDWgM6Axhi9odHRwOi8vY3JsLnRoYXd0ZS5jb20vVGhhd3RlUHJlbWl1bVNl
cnZlckNBLmNybDAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9v
Y3NwLnRoYXd0ZS5jb20wDQYJKoZIhvcNAQEFBQADgYEATPuxZbtJJSPmXvfrr1yz
xqM06IwTZ6UU0lZRG7I0WufMjNMKdpn8hklUhE17mxAhGSpewLVVeLR7uzBLFkuC
X7wMXxhoYdJZtNai72izU6Rd1oknao7diahvRxPK4IuQ7y2oZ511/4T4vgY6iRAj
q4q76HhPJrVRL/sduaiu+gYwggKZMIICAqADAgECAgEAMA0GCSqGSIb3DQEBBAUA
MIGHMQswCQYDVQQGEwJaQTEiMCAGA1UECBMZRk9SIFRFU1RJTkcgUFVSUE9TRVMg
T05MWTEdMBsGA1UEChMUVGhhd3RlIENlcnRpZmljYXRpb24xFzAVBgNVBAsTDlRF
U1QgVEVTVCBURVNUMRwwGgYDVQQDExNUaGF3dGUgVGVzdCBDQSBSb290MB4XDTk2
MDgwMTAwMDAwMFoXDTIwMTIzMTIxNTk1OVowgYcxCzAJBgNVBAYTAlpBMSIwIAYD
VQQIExlGT1IgVEVTVElORyBQVVJQT1NFUyBPTkxZMR0wGwYDVQQKExRUaGF3dGUg
Q2VydGlmaWNhdGlvbjEXMBUGA1UECxMOVEVTVCBURVNUIFRFU1QxHDAaBgNVBAMT
E1RoYXd0ZSBUZXN0IENBIFJvb3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
ALV9kG+Os6x/DOhm+tKUQfzVMWGhE95sFmEtkMMTX2Zi4n6i6BvzoReJ5njzt1LF
cqu4EUk9Ji20egKKfmqRzmQFLP7+1niSdfJEUE7cKY40QoI99270PTrLjJeaMcCl
+AYl+kD+RL5BtuKKU3PurYcsCsre6aTvjMcqpTJOGeSPAgMBAAGjEzARMA8GA1Ud
EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAgozj7BkD9O8si2V0v+EZ/t7E
fz/LC8y6mD7IBUziHy5/53ymGAGLtyhXHvX+UIE6UWbHro3IqVkrmY5uC93Z2Wew
A/6edK3KFUcUikrLeewM7gmqsiASEKx2mKRKlu12jXyNS5tXrPWRDvUKtFC1uL9a
12rFAQS2BkIk7aU+ghYxAA==
-----END PKCS7-----

Armazene-o como zlex.p7b
6. Importe o certificado assinado pela CA para o keystore.

keytool -import -trustcacerts -alias www.zlex.org -file d:\zlex.p7b -keystore d:\zlex.keystore -v

A senha que uso aqui é 123456

Saída do console:

输入keystore密码:

回复中的最高级认证:

所有者:CN=Thawte Test CA Root, OU=TEST TEST TEST, O=Thawte Certification, ST=FOR
 TESTING PURPOSES ONLY, C=ZA
签发人:CN=Thawte Test CA Root, OU=TEST TEST TEST, O=Thawte Certification, ST=FOR
 TESTING PURPOSES ONLY, C=ZA
序列号:0
有效期: Thu Aug 01 08:00:00 CST 1996Fri Jan 01 05:59:59 CST 2021
证书指纹:
         MD5:5E:E0:0E:1D:17:B7:CA:A5:7D:36:D6:02:DF:4D:26:A4
         SHA1:39:C6:9D:27:AF:DC:EB:47:D6:33:36:6A:B2:05:F1:47:A9:B4:DA:EA
         签名算法名称:MD5withRSA
         版本: 3

扩展:

#1: ObjectId: 2.5.29.19 Criticality=true
BasicConstraints:[
  CA:true
  PathLen:2147483647
]


... 是不可信的。 还是要安装回复? []Y
认证回复已安装在 keystore中
[正在存储 d:\zlex.keystore]

7. Posicionamento do nome de domínio
Posicione o nome de domínio www.zlex.org nesta máquina. Abra o arquivo C:\Windows\System32\drivers\etc\hosts e vincule www.zlex.org a esta máquina. Anexe 127.0.0.1 www.zlex.org ao final do arquivo. Agora visite http://www.zlex.org através da barra de endereço, ou através do comando ping, se a máquina puder ser localizada, o mapeamento do nome de domínio está feito.

8. Configurar servidor.xml

<Connector
			keystoreFile="conf/zlex.keystore"
			keystorePass="123456" 
			truststoreFile="conf/zlex.keystore"    
			truststorePass="123456"     
			SSLEnabled="true"
			URIEncoding="UTF-8"
			clientAuth="false"			
			maxThreads="150"
			port="443"
			protocol="HTTP/1.1"
			scheme="https"
			secure="true"
			sslProtocol="TLS" />

Copie o arquivo zlex.keystore para o diretório conf do tomcat e reinicie o tomcat. Visitando https://www.zlex.org/ descobrimos que a rede era um pouco lenta. Após cerca de 5 segundos, a página web é exibida normalmente e ao mesmo tempo, conforme mostrado na figura abaixo:
Vários algoritmos de criptografia Java
O navegador verificou a validade da organização CA.

Abra o certificado, conforme mostrado na figura a seguir:
Vários algoritmos de criptografia Java

Ajuste a classe de teste:

import static org.junit.Assert.*;
 
import java.io.DataInputStream;
import java.io.InputStream;
import java.net.URL;
 
import javax.net.ssl.HttpsURLConnection;
 
import org.junit.Test;
 
/**
 * 
 * @author 梁栋
 * @version 1.0
 * @since 1.0
 */
public class CertificateCoderTest {
    
    
    private String password = "123456";
    private String alias = "www.zlex.org";
    private String certificatePath = "d:/zlex.cer";
    private String keyStorePath = "d:/zlex.keystore";
 
    @Test
    public void test() throws Exception {
    
    
        System.err.println("公钥加密——私钥解密");
        String inputStr = "Ceritifcate";
        byte[] data = inputStr.getBytes();
 
        byte[] encrypt = CertificateCoder.encryptByPublicKey(data,
                certificatePath);
 
        byte[] decrypt = CertificateCoder.decryptByPrivateKey(encrypt,
                keyStorePath, alias, password);
        String outputStr = new String(decrypt);
 
        System.err.println("加密前: " + inputStr + "\n\r" + "解密后: " + outputStr);
 
        // 验证数据一致
        assertArrayEquals(data, decrypt);
 
        // 验证证书有效
        assertTrue(CertificateCoder.verifyCertificate(certificatePath));
 
    }
 
    @Test
    public void testSign() throws Exception {
    
    
        System.err.println("私钥加密——公钥解密");
 
        String inputStr = "sign";
        byte[] data = inputStr.getBytes();
 
        byte[] encodedData = CertificateCoder.encryptByPrivateKey(data,
                keyStorePath, alias, password);
 
        byte[] decodedData = CertificateCoder.decryptByPublicKey(encodedData,
                certificatePath);
 
        String outputStr = new String(decodedData);
        System.err.println("加密前: " + inputStr + "\n\r" + "解密后: " + outputStr);
        assertEquals(inputStr, outputStr);
 
        System.err.println("私钥签名——公钥验证签名");
        // 产生签名
        String sign = CertificateCoder.sign(encodedData, keyStorePath, alias,
                password);
        System.err.println("签名:\r" + sign);
 
        // 验证签名
        boolean status = CertificateCoder.verify(encodedData, sign,
                certificatePath);
        System.err.println("状态:\r" + status);
        assertTrue(status);
 
    }
 
    @Test
    public void testHttps() throws Exception {
    
    
        URL url = new URL("https://www.zlex.org/examples/");
        HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
 
        conn.setDoInput(true);
        conn.setDoOutput(true);
 
        CertificateCoder.configSSLSocketFactory(conn, password, keyStorePath,
                keyStorePath);
 
        InputStream is = conn.getInputStream();
 
        int length = conn.getContentLength();
 
        DataInputStream dis = new DataInputStream(is);
        byte[] data = new byte[length];
        dis.readFully(data);
 
        dis.close();
        conn.disconnect();
        System.err.println(new String(data));
    }
}

Execute novamente, a verificação foi aprovada!
Assim, realizamos o processo de autenticação baseado no protocolo SSL. O método testHttps da classe de teste simula o acesso HTTPS de um navegador.

Acho que você gosta

Origin blog.csdn.net/qq_43842093/article/details/132643396
Recomendado
Clasificación