Gids voor de coderingsklasse

1. Overzicht

Simpel gezegd, codering is het proces waarbij een bericht zodanig wordt gecodeerd dat alleen geautoriseerde gebruikers het kunnen begrijpen of er toegang toe hebben.

Het bericht, aangeduid als platte tekst, is versleuteld met behulp van een versleutelingsalgoritme - een cijfer - genereren cijfertekst die alleen door geautoriseerde gebruikers kunnen worden gelezen via decodering.

In dit artikel beschrijven we in detail de kern Cijfer class, die cryptografische codering en decoderingsfunctionaliteit biedt in Java.

2. Coderingsklasse

Java Cryptography Extension (JCE) is de onderdeel van de Java Cryptography Architecture (JCA) die een applicatie voorziet van cryptografische codes voor gegevensversleuteling en -ontsleuteling, evenals het hashen van privégegevens.

De Cijfer class - gelegen in de javax.crypto pakket - vormt de kern van het JCE-raamwerk en biedt de functionaliteit voor codering en decodering.

2.1. Cipher instantiatie

Om een Cijfer object, wij bel de statische getInstance methode, door de naam van de gevraagde transformatie door te geven. Optioneel kan de naam van een provider worden gespecificeerd.

Laten we een voorbeeldklasse schrijven die de instantiatie van a illustreert Cijfer:

openbare klasse Encryptor {openbare byte [] encryptMessage (byte [] bericht, byte [] keyBytes) genereert InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException {Cipher cipher = Cipher.getInstance ("AES / ECB / PKCS5Padding"); // ...}}

De transformatie AES / ECB / PKCS5Padding vertelt de getInstance methode om het Cijfer object als een AES-cijfer met ECB-werkingsmodus en PKCS5-opvulschema.

We kunnen ook het Cijfer object door alleen het algoritme in de transformatie op te geven:

Cipher cipher = Cipher.getInstance ("AES");

In dit geval gebruikt Java providerspecifieke standaardwaarden voor de modus en het opvulschema.

Let daar op getInstance zal een NoSuchAlgorithmException als de transformatie is nul, leeg of in een ongeldig formaat, of als de provider dit niet ondersteunt.

Het zal een NoSuchPaddingException als de transformatie een niet-ondersteund opvulschema bevat.

2.2. Draad-veiligheid

De Cijfer class is een stateful zonder enige vorm van interne synchronisatie. In feite, methoden zoals in het() of bijwerken() verandert de interne toestand van een bepaald Cijfer voorbeeld.

Daarom, de Cijfer class is niet thread-safe. Dus we zouden er een moeten maken Cijfer instantie per coderings- / decoderingsbehoefte.

2.3. Sleutels

De Sleutel interface vertegenwoordigt sleutels voor cryptografische bewerkingen. Sleutels zijn ondoorzichtige containers die een gecodeerde sleutel, het coderingsformaat van de sleutel en het cryptografische algoritme bevatten.

Sleutels worden doorgaans verkregen via sleutelgeneratoren, certificaten of sleutelspecificaties met behulp van een sleutelfabriek.

Laten we een symmetrisch maken Sleutel van de geleverde sleutelbytes:

SecretKey secretKey = nieuwe SecretKeySpec (keyBytes, "AES");

2.4. Cipher initialisatie

We noemen de in het() methode om de C te initialiserenipher voorwerp met een Sleutel of Certificaat en een opmode met vermelding van de werkingsmodus van het cijfer.

Optioneel, we kunnen een bron van willekeur passeren. Standaard is een SecureRandom implementatie van de geïnstalleerde provider met de hoogste prioriteit wordt gebruikt. Anders gebruikt het een door het systeem geleverde bron.

We kunnen optioneel een set algoritme-specifieke parameters specificeren. We kunnen bijvoorbeeld een IvParameterSpec naar specificeer een initialisatievector.

Dit zijn de beschikbare bedieningsmodi voor codering:

  • ENCRYPT_MODE: initialiseren cijfer bezwaar maken tegen de coderingsmodus
  • DECRYPT_MODE: initialiseren cijfer bezwaar maken tegen de decoderingsmodus
  • WRAP_MODE: initialiseren cijfer object naar key-wrapping-modus
  • UNWRAP_MODE: initialiseren cijfer bezwaar maken tegen de modus voor het uitpakken van sleutels

Laten we het Cijfer voorwerp:

Cipher cipher = Cipher.getInstance ("AES / ECB / PKCS5Padding"); SecretKey secretKey = nieuwe SecretKeySpec (keyBytes, "AES"); cipher.init (Cipher.ENCRYPT_MODE, secretKey); // ...

Nu de in het methode gooit een InvalidKeyException als de geleverde sleutel niet geschikt is voor het initialiseren van de code, zoals wanneer een sleutellengte / codering ongeldig is.

Het wordt ook gegenereerd wanneer het cijfer bepaalde algoritmeparameters vereist die niet met de sleutel kunnen worden bepaald, of als de sleutel een sleutelgrootte heeft die groter is dan de maximaal toegestane sleutelgrootte (bepaald op basis van de geconfigureerde JCE-jurisdictiebeleidbestanden).

Laten we een voorbeeld bekijken met een Certificaat:

openbare byte [] encryptMessage (byte [] bericht, certificaatcertificaat) genereert InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException {Cipher cipher = Cipher.getInstance ("RSA / ECB / PKCS1Padding"); cipher.init (Cipher.ENCRYPT_MODE, certificaat); // ...}

De Cijfer object haalt de openbare sleutel voor gegevensversleuteling uit het certificaat door de getPublicKey methode.

2.5. Versleuteling en ontsleuteling

Na het initialiseren van het Cijfer object noemen we de doFinal () methode om de versleuteling of ontsleuteling uit te voeren. Deze methode retourneert een byte-array die het gecodeerde of gedecodeerde bericht bevat.

De doFinal () methode reset ook de Cijfer bezwaar maken tegen de staat waarin het zich bevond toen het eerder werd geïnitialiseerd via een aanroep naar in het() methode, waardoor de Cijfer object beschikbaar om aanvullende berichten te versleutelen of te ontsleutelen.

Laten we bellen doFinal in onze encryptMessage methode:

openbare byte [] encryptMessage (byte [] bericht, byte [] keyBytes) genereert InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException {Cipher cipher = Cipher.getInstance ("AES / ECB / PKCS5); SecretKey secretKey = nieuwe SecretKeySpec (keyBytes, "AES"); cipher.init (Cipher.ENCRYPT_MODE, secretKey); return cipher.doFinal (bericht); }

Om een ​​decoderingsbewerking uit te voeren, wijzigen we de opmode naar DECRYPT_MODE:

openbare byte [] decryptMessage (byte [] encryptedMessage, byte [] keyBytes) genereert NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {Cipher cipher = Cipher.getInstance (") AES / ECB / PK; SecretKey secretKey = nieuwe SecretKeySpec (keyBytes, "AES"); cipher.init (Cipher.DECRYPT_MODE, secretKey); retourneer cipher.doFinal (encryptedMessage); }

2.6. Aanbieders

Ontworpen om een ​​op providers gebaseerde architectuur te gebruiken, de JCE zorgt ervoor dat gekwalificeerde cryptografiebibliotheken zoals BouncyCastle kunnen worden aangesloten als beveiligingsproviders en dat nieuwe algoritmen naadloos kunnen worden toegevoegd.

Laten we nu BouncyCastle toevoegen als beveiligingsprovider. We kunnen een beveiligingsprovider statisch of dynamisch toevoegen.

Om BouncyCastle statisch toe te voegen, wijzigen we de java.security het dossier gevestigd in / jre / lib / security map.

We voegen de regel toe aan het einde van de lijst:

... security.provider.4 = com.sun.net.ssl.internal.ssl.Provider security.provider.5 = com.sun.crypto.provider.SunJCE security.provider.6 = sun.security.jgss.SunProvider security.provider.7 = org.bouncycastle.jce.provider.BouncyCastleProvider

Bij het toevoegen van de eigenschap provider heeft de eigenschapsleutel de indeling security.provider.N waar het nummer N is er één meer dan de laatste op de lijst.

We kunnen de beveiligingsprovider BouncyCastle ook dynamisch toevoegen zonder het beveiligingsbestand te hoeven wijzigen:

Security.addProvider (nieuwe BouncyCastleProvider ());

We kunnen nu de provider specificeren tijdens de coderingsinitialisatie:

Cipher cipher = Cipher.getInstance ("AES / ECB / PKCS5Padding", "BC");

BC specificeert BouncyCastle als de provider. We kunnen de lijst met geregistreerde providers krijgen via de Security.getProviders () methode.

3. Testen van versleuteling en ontsleuteling

Laten we een voorbeeldtest schrijven om de versleuteling en ontsleuteling van berichten te illustreren.

In deze test gebruiken we een AES-coderingsalgoritme met een 128-bits sleutel en stellen we vast dat het gedecodeerde resultaat gelijk is aan de originele berichttekst:

@Test public void whenIsEncryptedAndDecrypted_thenDecryptedEqualsOriginal () gooit uitzondering {String encryptionKeyString = "thisisa128bitkey"; String originalMessage = "Dit is een geheim bericht"; byte [] encryptionKeyBytes = encryptionKeyString.getBytes (); Cipher cipher = Cipher.getInstance ("AES / ECB / PKCS5Padding"); SecretKey secretKey = nieuwe SecretKeySpec (encryptionKeyBytes, "AES"); cipher.init (Cipher.ENCRYPT_MODE, secretKey); byte [] encryptedMessageBytes = cipher.doFinal (message.getBytes ()); cipher.init (Cipher.DECRYPT_MODE, secretKey); byte [] decryptedMessageBytes = cipher.doFinal (encryptedMessageBytes); assertThat (originalMessage) .isEqualTo (new String (decryptedMessageBytes)); }

4. Conclusie

In dit artikel hebben we de Cijfer klasse en gepresenteerde gebruiksvoorbeelden. Meer details over de Cijfer class en het JCE Framework zijn te vinden in de klassedocumentatie en de Java Cryptography Architecture (JCA) Reference Guide.

Implementatie van al deze voorbeelden en codefragmenten kan gevonden worden over op GitHub. Dit is een op Maven gebaseerd project, dus het zou gemakkelijk moeten kunnen worden geïmporteerd en uitgevoerd zoals het is.