Digitális aláírások Java-ban

Java Top

Most jelentettem be az újat Tanulj tavaszt tanfolyam, amelynek középpontjában az 5. tavasz és a tavaszi bakancs 2 alapjai állnak:

>> ELLENŐRIZZE A FOLYAMATOT

1. Áttekintés

Ebben az oktatóanyagban megismerjük a Digitális aláírás mechanizmus és hogyan tudjuk megvalósítani a Java Cryptography Architecture (JCA) segítségével. Felfedezzük a KeyPair, MessageDigest, Cipher, KeyStore, Certificate, és Aláírás JCA API-k.

Kezdjük azzal, hogy megértsük, mi a digitális aláírás, hogyan hozható létre kulcspár és miként lehet hitelesíteni a nyilvános kulcsot egy tanúsító hatóságtól (CA). Ezt követően meglátjuk, hogyan lehet a digitális aláírást megvalósítani az alacsony és a magas szintű JCA API-k segítségével.

2. Mi a digitális aláírás?

2.1. Digitális aláírás meghatározása

A digitális aláírás egy technika a következők biztosítására:

  • Integritás: az üzenet nem változott szállítás közben
  • Hitelesség: az üzenet szerzője valóban az, akinek állítják magukat
  • Nem tagadás: az üzenet szerzője később nem tagadhatja meg, hogy ők voltak a forrás

2.2. Üzenet küldése digitális aláírással

Műszakilag aa digitális aláírás az üzenet titkosított kivonata (kivonat, ellenőrző összeg). Ez azt jelenti, hogy kivonatot készítünk egy üzenetből, és titkosítjuk egy privát kulccsal a választott algoritmus szerint.

Ezután az üzenet, a titkosított kivonat, a megfelelő nyilvános kulcs és az algoritmus elküldésre kerül. Ez digitális aláírással rendelkező üzenetnek minősül.

2.3. Digitális aláírás fogadása és ellenőrzése

A digitális aláírás ellenőrzéséhez az üzenetvevő új kivonatot generál a fogadott üzenetből, a nyilvános kulcs segítségével visszafejti a beérkezett titkosított kivonatot, és összehasonlítja azokat. Ha egyeznek, a digitális aláírást állítólag ellenőrizni kell.

Meg kell jegyeznünk, hogy csak az üzenet kivonatát kódoljuk, magát az üzenetet nem. Más szóval, a Digitális aláírás nem próbálja titokban tartani az üzenetet. Digitális aláírásunk csak azt bizonyítja, hogy az üzenet nem változott szállítás közben.

Az aláírás ellenőrzését követően biztosak vagyunk abban, hogy csak a privát kulcs tulajdonosa lehet az üzenet szerzője.

3. Digitális tanúsítvány és nyilvános kulcs azonosítója

A tanúsítvány olyan dokumentum, amely egy személyazonosságot társít egy adott nyilvános kulcshoz. A tanúsítványokat egy tanúsító hatóság (CA) nevű harmadik fél írja alá.

Tudjuk, hogy ha a közzétett nyilvános kulccsal visszafejtett kivonat megegyezik a tényleges kivonattal, akkor az üzenet aláírásra kerül. Honnan tudhatjuk azonban, hogy a nyilvános kulcs valóban a megfelelő entitástól származik? Ezt digitális tanúsítványok segítségével oldják meg.

A digitális tanúsítvány tartalmaz egy nyilvános kulcsot, amelyet maga is aláír egy másik entitás. Az entitás aláírását maga is ellenőrizheti egy másik entitás és így tovább. Végül megvan az úgynevezett tanúsítványlánc. Minden felsőbb entitás hitelesíti a következő entitás nyilvános kulcsát. A legfelső szintű entitás önaláírás, ami azt jelenti, hogy nyilvános kulcsát saját privát kulcsa írja alá.

Az X.509 a leggyakrabban használt tanúsítványformátum, amelyet bináris formátumban (DER) vagy szöveges formátumban (PEM) szállítanak. A JCA ennek megvalósítását már a X509Tanúsítvány osztály.

4. KeyPair menedzsment

Mivel a Digitális aláírás magán- és nyilvános kulcsot használ, a JCA osztályokat fogjuk használni PrivateKey és PublicKey üzenet aláírására és ellenőrzésére.

4.1. Kulcspár beszerzése

Privát és nyilvános kulcs kulcspárjának létrehozása, használjuk a Java-t kulcstartó.

Generáljunk egy kulcspárt a genkeypair parancs:

keytool -genkeypair -alias senderKeyPair -keyalg RSA -keysize 2048 \ -dname "CN = Baeldung" -validity 365 -storetype PKCS12 \ -keystore sender_keystore.p12 -storepass changeit

Ez létrehoz egy privát kulcsot és a hozzá tartozó nyilvános kulcsot számunkra. A nyilvános kulcs egy X.509 saját aláírású tanúsítványba van csomagolva, amely viszont egy elemű tanúsítványláncba kerül. A tanúsítványláncot és a magánkulcsot a Keystore fájlban tároljuk sender_keystore.p12, amelyet a KeyStore API segítségével dolgozhatunk fel.

Itt a PKCS12 kulcstároló formátumot használtuk, mivel ez a szabványos és a Java által védett JKS formátumhoz képest ajánlott. Emellett emlékeznünk kell a jelszóra és az álnévre, mivel a következő alfejezetben használjuk őket a Keystore fájl betöltésekor.

4.2. A privát kulcs betöltése aláírásra

Az üzenet aláírásához szükségünk van a PrivateKey.

Használni a KeyStore API és az előző Keystore fájl, sender_keystore.p12, kaphatunk egy PrivateKey tárgy:

KeyStore keyStore = KeyStore.getInstance ("PKCS12"); keyStore.load (új FileInputStream ("sender_keystore.p12"), "changeit"); PrivateKey privateKey = (PrivateKey) keyStore.getKey ("senderKeyPair", "changeit");

4.3. A nyilvános kulcs közzététele

A nyilvános kulcs közzététele előtt először el kell döntenünk, hogy önaláírt vagy CA által aláírt tanúsítványt fogunk-e használni.

Önaláírt tanúsítvány használatakor csak a Keystore fájlból kell exportálnunk. Megtehetjük ezt a exportcert parancs:

keytool -exportcert -alias senderKeyPair -storetype PKCS12 \ -keystore sender_keystore.p12 -file \ sender_certificate.cer -rfc -storepass changeit

Másképp, ha CA által aláírt tanúsítvánnyal fogunk dolgozni, akkor létre kell hoznunk egy tanúsítvány aláírási kérelmet (CSR). Ezt a certreq parancs:

keytool -certreq -alias senderKeyPair -storetype PKCS12 \ -keystore sender_keystore.p12 -file -rfc \ -storepass changeit> sender_certificate.csr

A CSR fájl, sender_certificate.csr, ezután elküldik egy tanúsító hatóságnak aláírás céljából. Ha ez megtörtént, kapunk egy aláírt nyilvános kulcsot, amelyet X.509 tanúsítványba csomagolunk, akár bináris (DER), akár szöveges (PEM) formátumban. Itt használtuk a rfc opció PEM formátumhoz.

A CA-tól kapott nyilvános kulcs, sender_certificate.cer, most egy hitelesítésszolgáltató írta alá, és elérhetővé tehető az ügyfelek számára.

4.4. Nyilvános kulcs betöltése ellenőrzés céljából

A nyilvános kulcshoz való hozzáférés esetén a vevő betöltheti azt a kulcstárába a importcert parancs:

keytool -importcert -alias receiverKeyPair -storetype PKCS12 \ -keystore receiver_keystore.p12 -file \ sender_certificate.cer -rfc -storepass changeit

És a KeyStore API, mint korábban, kaphatunk egy PublicKey példa:

KeyStore keyStore = KeyStore.getInstance ("PKCS12"); keyStore.load (új FileInputStream ("receiver_keytore.p12"), "changeit"); Tanúsítvány tanúsítvány = keyStore.getCertificate ("receiverKeyPair"); PublicKey publicKey = certificate.getPublicKey ();

Most, hogy van egy PrivateKey a feladó oldalán, és a PublicKey a vevő oldalon megkezdhetjük az aláírás és az ellenőrzés folyamatát.

5. Digitális aláírás Üzenet feldolgozása és Rejtjel Osztályok

Mint láttuk, a digitális aláírás hasításon és titkosításon alapul.

Általában a Üzenet feldolgozása osztály SHA-val vagy MD5-vel a hasheléshez és a Rejtjel osztály a titkosításhoz.

Most kezdjük el a digitális aláírás mechanizmusainak megvalósítását.

5.1. Hash üzenet létrehozása

Az üzenet lehet karakterlánc, fájl vagy bármilyen más adat. Tehát vegyük egy egyszerű fájl tartalmát:

byte [] messageBytes = Files.readAllBytes (Paths.get ("message.txt"));

Most, használva Üzenet feldolgozása, használjuk a megemészteni módszer a kivonat létrehozására:

MessageDigest md = MessageDigest.getInstance ("SHA-256"); bájt [] messageHash = md.digest (messageBytes);

Itt az SHA-256 algoritmust használtuk, amely a leggyakrabban használt. További alternatívák: MD5, SHA-384 és SHA-512.

5.2. A generált hash titkosítása

Egy üzenet titkosításához algoritmusra és privát kulcsra van szükségünk. Itt az RSA algoritmust fogjuk használni. A DSA algoritmus egy másik lehetőség.

Hozzunk létre egy Rejtjel példányt, és inicializálja a titkosításhoz. Akkor felhívjuk a doFinal () módszer a korábban kivonatolt üzenet titkosításához:

Cipher rejtjel = Cipher.getInstance ("RSA"); cipher.init (Cipher.ENCRYPT_MODE, privateKey); bájt [] digitalSignature = rejtjel.doFinal (messageHash);

Az aláírás fájlba menthető, hogy később elküldhesse:

Files.write (Paths.get ("digital_signature_1"), digitalSignature);

Ekkor az üzenet, a digitális aláírás, a nyilvános kulcs és az algoritmus mind elküldésre kerül, és a vevő ezeket az információkat felhasználhatja az üzenet integritásának ellenőrzésére.

5.3. Aláírás ellenőrzése

Amikor üzenetet kapunk, ellenőriznünk kell annak aláírását. Ehhez visszafejtjük a beérkezett, titkosított kivonatot, és összehasonlítjuk a kapott üzenet kivonatával.

Olvassuk el a kapott digitális aláírást:

byte [] encryptedMessageHash = Files.readAllBytes (Útvonalak.get ("digital_signature_1"));

A visszafejtéshez létrehozunk egy Rejtjel példa. Aztán felhívjuk a doFinal módszer:

Cipher rejtjel = Cipher.getInstance ("RSA"); cipher.init (Cipher.DECRYPT_MODE, publicKey); byte [] decryptedMessageHash = rejtjel.doFinal (encryptedMessageHash);

Ezután létrehozunk egy új üzenet kivonatot a kapott üzenetből:

byte [] messageBytes = Files.readAllBytes (Paths.get ("message.txt")); MessageDigest md = MessageDigest.getInstance ("SHA-256"); bájt [] newMessageHash = md.digest (messageBytes);

Végül ellenőrizzük, hogy az újonnan létrehozott kivonat megfelel-e a visszafejtettnek:

logikai isCorrect = Tömbök.egyenlő (visszafejtettMessageHash, newMessageHash);

Ebben a példában a szövegfájlt használtuk message.txt szimulálni egy elküldeni kívánt üzenetet, vagy az érkezett üzenet törzsének helyét. Normális esetben azt vártuk, hogy üzenetünket az aláírás mellett kapjuk meg.

6. Digitális aláírás a Aláírás Osztály

Eddig az alacsony szintű API-kat használtuk saját digitális aláírás-ellenőrzési folyamatunk felépítéséhez. Ez segít megérteni a működését, és lehetővé teszi számunkra, hogy testre szabjuk.

Azonban a JCA már dedikált API-t kínál a Aláírás osztály.

6.1. Üzenet aláírása

Az aláírás folyamatának megkezdéséhez először létrehozzuk a Aláírás osztály. Ehhez szükségünk van egy aláíró algoritmusra. Ezután inicializáljuk a Aláírás a magánkulcsunkkal:

Aláírás aláírás = Signature.getInstance ("SHA256withRSA"); aláírás.initSign (privateKey);

Az általunk választott aláíró algoritmus, SHA256RSA-val ebben a példában, egy kivonatoló algoritmus és egy titkosító algoritmus kombinációja. Egyéb alternatívák: SHA1 az RSA-val, SHA1DSA-val, és MD5RSA-valtöbbek között.

Ezután aláírjuk az üzenet bájt tömbjét:

byte [] messageBytes = Files.readAllBytes (Paths.get ("message.txt")); aláírás.update (messageBytes); bájt [] digitalSignature = aláírás.jel (();

Az aláírást fájlba menthetjük későbbi továbbítás céljából:

Files.write (Paths.get ("digital_signature_2"), digitalSignature);

6.2. Az aláírás ellenőrzése

A kapott aláírás ellenőrzéséhez ismét létrehozunk egy Aláírás példa:

Aláírás aláírás = Signature.getInstance ("SHA256wSARSA");

Ezután inicializáljuk a Aláírás objektum ellenőrzése céljából a initVerify módszer, amely nyilvános kulcsot igényel:

aláírás.initVerify (publicKey);

Ezután hozzá kell adnunk a kapott üzenet bájtokat az aláírásobjektumhoz a frissítés módszer:

byte [] messageBytes = Files.readAllBytes (Paths.get ("message.txt")); aláírás.update (messageBytes);

És végül ellenőrizhetjük az aláírást a igazolja módszer:

logikai isCorrect = aláírás.ellenőrzés (kapottSignature);

7. Következtetés

Ebben a cikkben először megvizsgáltuk a digitális aláírás működését és a digitális tanúsítvány bizalmának megteremtését. Ezután megvalósítottunk egy digitális aláírást a Üzenet feldolgozása,Rejtjel, és Aláírás osztályok a Java Cryptography Architecture-től.

Részletesen láttuk, hogyan kell aláírni az adatokat a magánkulcs segítségével, és hogyan lehet az aláírást nyilvános kulccsal ellenőrizni.

Mint mindig, a cikk kódja is elérhető a GitHubon.

Java alsó

Most jelentettem be az újat Tanulj tavaszt tanfolyam, amelynek középpontjában az 5. tavasz és a tavaszi bakancs 2 alapjai állnak:

>> ELLENŐRIZZE A FOLYAMATOT

$config[zx-auto] not found$config[zx-overlay] not found