Olá Habr! Apresento a você a tradução do artigo 9 da "Java KeyStore", de Jakob Jenkov, de uma série de artigos para iniciantes que desejam aprender o básico da criptografia em Java.
Sumário:
- Criptografia Java
- Cifra Java
- Messagedigest
- Mac
- Assinatura
- Par de chaves
- Keygenerator
- KeyPairGenerator
- Keystore
- Keytool
- Certificado
- CertificateFactory
- CertPath
Keystore
O Java KeyStore é um armazenamento de chaves do tipo banco de dados representado pela classe KeyStore ( java.security.KeyStore ). O armazenamento pode ser gravado em disco e lido novamente, pode ser protegido por senha e cada registro de chave no armazenamento de chaves pode ser protegido com sua própria senha, o que torna a classe KeyStore
um mecanismo útil para trabalhar com chaves de criptografia com segurança. Um keystore pode conter chaves dos seguintes tipos:
- Chaves privadas
- Chaves e certificados públicos (Chaves públicas + certificados)
- Chaves secretas
Chaves privadas e públicas são usadas na criptografia assimétrica. A chave pública pode ter um certificado associado. Um certificado é um documento que comprova a identidade de uma pessoa, organização ou dispositivo que afirma possuir uma chave pública. O certificado geralmente é assinado digitalmente pela parte confiável como prova. Chaves privadas são usadas na criptografia simétrica. Na maioria dos casos, ao configurar uma conexão segura, as chaves simétricas são inferiores às assimétricas, portanto, na maioria das vezes, você armazena chaves públicas e privadas no keystore.
Criando um keystore
Você pode criar uma instância do KeyStore
chamando seu método getInstance()
. Aqui está um exemplo de criação de uma instância de uma classe:
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
Este exemplo cria uma instância padrão do KeyStore
. Você também pode criar instâncias do KeyStore com um formato de armazenamento de chaves diferente, passando um parâmetro para o método getInstance()
. Por exemplo, criando uma instância do keystore PKCS12
:
KeyStore keyStore = KeyStore.getInstance("PKCS12");
Download do keystore
Antes de poder usar uma instância de um keystore, você deve baixá-lo. As instâncias da classe KeyStore
geralmente KeyStore
gravadas em disco ou outro armazenamento para uso posterior, porque a classe KeyStore
pressupõe que você deve ler seus dados antes de poder usá-los. No entanto, você pode inicializar uma instância vazia do KeyStore
sem dados, como você verá mais adiante.
Os dados são carregados de um arquivo ou outro armazenamento chamando o método load()
, que utiliza dois parâmetros:
InputStream
partir do qual os dados serão carregados.char[]
Uma matriz de caracteres que contém a senha do keystore.
Aqui está um exemplo de carregamento de um keystore:
char[] keyStorePassword = "123abc".toCharArray(); try(InputStream keyStoreData = new FileInputStream("keystore.ks")){ keyStore.load(keyStoreData, keyStorePassword); }
Este exemplo carrega o arquivo keystore.ks keystore. Se você não deseja carregar nenhum dado no keystore, basta passar null
para o parâmetro InputStream
. É assim que o carregamento de um keystore vazio se parece:
keyStore3.load(null, keyStorePassword);
Uma instância da classe KeyStore
sempre KeyStore
ser carregada com dados ou null
. Caso contrário, o keystore não será inicializado e todas as chamadas para seus métodos gerarão exceções.
Recebendo chaves
Você pode obter as chaves de uma instância da classe KeyStore
por meio do método getEntry()
. O registro do keystore é mapeado para um alias que identifica a chave e é protegido por senha. Portanto, para acessar a chave, você deve passar o alias e a senha da chave para o método getEntry()
. Aqui está um exemplo de acesso de gravação a uma instância do KeyStore
:
char[] keyPassword = "789xyz".toCharArray(); KeyStore.ProtectionParameter entryPassword = new KeyStore.PasswordProtection(keyPassword); KeyStore.Entry keyEntry = keyStore3.getEntry("keyAlias", entryPassword);
Se você souber que o registro que deseja acessar é a chave privada, poderá converter a instância de KeyStore.Entry
em KeyStore.PrivateKeyEntry
. Aqui está o que parece:
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore3.getEntry("keyAlias", entryPassword);
Após KeyStore.PrivateKeyEntry
para KeyStore.PrivateKeyEntry
você pode acessar a chave privada, o certificado e a cadeia de certificados usando os seguintes métodos:
getPrivateKey()
getCertificate()
getCertificateChain()
Armazenamento de chaves
Você também pode colocar chaves em uma instância da classe KeyStore
. Um exemplo de colocação de uma chave secreta (chave simétrica) em uma instância do KeyStore
:
SecretKey secretKey = getSecretKey(); KeyStore.SecretKeyEntry secretKeyEntry = new KeyStore.SecretKeyEntry(secretKey); keyStore3.setEntry("keyAlias2", secretKeyEntry, entryPassword);
Armazenamento
Às vezes, você pode salvar o keystore em algum tipo de armazenamento (disco, banco de dados etc.) para poder carregá-lo novamente outra vez. Uma instância da classe KeyStore
salva chamando o método store()
. Um exemplo:
char[] keyStorePassword = "123abc".toCharArray(); try (FileOutputStream keyStoreOutputStream = new FileOutputStream("data/keystore.ks")) { keyStore3.store(keyStoreOutputStream, keyStorePassword); }