Crittografia Java - Guida rapida

La crittografia è l'arte e la scienza per creare un sistema crittografico in grado di fornire la sicurezza delle informazioni.

La crittografia si occupa della protezione effettiva dei dati digitali. Si riferisce alla progettazione di meccanismi basati su algoritmi matematici che forniscono servizi fondamentali per la sicurezza delle informazioni. Si può pensare alla crittografia come alla creazione di un ampio toolkit contenente diverse tecniche nelle applicazioni di sicurezza.

Cos'è la crittoanalisi?

L'arte e la scienza di rompere il testo cifrato sono note come crittoanalisi.

La crittoanalisi è il ramo gemello della crittografia ed entrambi coesistono. Il processo crittografico produce il testo cifrato per la trasmissione o l'archiviazione. Implica lo studio del meccanismo crittografico con l'intenzione di romperli. La crittoanalisi viene utilizzata anche durante la progettazione delle nuove tecniche crittografiche per testarne i punti di forza della sicurezza.

Primitive di crittografia

Le primitive di crittografia non sono altro che gli strumenti e le tecniche in crittografia che possono essere utilizzate selettivamente per fornire una serie di servizi di sicurezza desiderati -

  • Encryption
  • Funzioni hash
  • Codici di autenticazione del messaggio (MAC)
  • Firme digitali

Crittografia in Java

Java Cryptography Architecture (JCA) è un insieme di API per implementare concetti di crittografia moderna come firme digitali, digest di messaggi, certificati, crittografia, generazione e gestione di chiavi e generazione sicura di numeri casuali ecc.

Utilizzando gli sviluppatori JCA possono creare le loro applicazioni integrandovi la sicurezza.

Per integrare la sicurezza nelle tue applicazioni piuttosto che dipendere dai complicati algoritmi di sicurezza puoi facilmente chiamare le rispettive API fornite in JCA per i servizi richiesti.

Le funzioni hash sono estremamente utili e compaiono in quasi tutte le applicazioni di sicurezza delle informazioni.

Una funzione hash è una funzione matematica che converte un valore di input numerico in un altro valore numerico compresso. L'input per la funzione hash è di lunghezza arbitraria ma l'output è sempre di lunghezza fissa.

Vengono chiamati i valori restituiti da una funzione hash message digest o semplicemente hash values. La seguente immagine ha illustrato la funzione hash.

Java fornisce una classe denominata MessageDigestche appartiene al pacchetto java.security. Questa classe supporta algoritmi come SHA-1, SHA 256, MD5 per convertire un messaggio di lunghezza arbitraria in un digest del messaggio.

Per convertire un determinato messaggio in un digest del messaggio, segui i passaggi indicati di seguito:

Passaggio 1: crea un oggetto MessageDigest

La classe MessageDigest fornisce un metodo denominato getInstance(). Questo metodo accetta una variabile String che specifica il nome dell'algoritmo da utilizzare e restituisce un oggetto MessageDigest che implementa l'algoritmo specificato.

Crea l'oggetto MessageDigest utilizzando il getInstance() metodo come mostrato di seguito.

MessageDigest md = MessageDigest.getInstance("SHA-256");

Passaggio 2: passare i dati all'oggetto MessageDigest creato

Dopo aver creato l'oggetto digest del messaggio, è necessario passarvi il messaggio / i dati. Puoi farlo usando ilupdate() metodo del MessageDigest class, questo metodo accetta un array di byte che rappresenta il messaggio e lo aggiunge / lo passa all'oggetto MessageDigest creato sopra.

md.update(msg.getBytes());

Passaggio 3: genera il digest del messaggio

Puoi generare il digest del messaggio utilizzando il file digest() metodo della classe MessageDigest questo metodo calcola la funzione hash sull'oggetto corrente e restituisce il digest del messaggio sotto forma di array di byte.

Genera il digest del messaggio utilizzando il metodo digest.

byte[] digest = md.digest();

Esempio

Di seguito è riportato un esempio che legge i dati da un file e genera un messaggio digest e lo stampa.

import java.security.MessageDigest;
import java.util.Scanner;

public class MessageDigestExample {
   public static void main(String args[]) throws Exception{
      //Reading data from user
      Scanner sc = new Scanner(System.in);
      System.out.println("Enter the message");
      String message = sc.nextLine();
	  
      //Creating the MessageDigest object  
      MessageDigest md = MessageDigest.getInstance("SHA-256");

      //Passing data to the created MessageDigest Object
      md.update(message.getBytes());
      
      //Compute the message digest
      byte[] digest = md.digest();      
      System.out.println(digest);  
     
      //Converting the byte array in to HexString format
      StringBuffer hexString = new StringBuffer();
      
      for (int i = 0;i<digest.length;i++) {
         hexString.append(Integer.toHexString(0xFF & digest[i]));
      }
      System.out.println("Hex format : " + hexString.toString());     
   }
}

Produzione

Il programma di cui sopra genera il seguente output:

Enter the message
Hello how are you
[B@55f96302
Hex format: 2953d33828c395aebe8225236ba4e23fa75e6f13bd881b9056a3295cbd64d3

MAC (Message Aautenticazione Code) è una tecnica crittografica a chiave simmetrica per fornire l'autenticazione dei messaggi. Per stabilire il processo MAC, il mittente e il destinatario condividono una chiave simmetrica K.

In sostanza, un MAC è un checksum crittografato generato sul messaggio sottostante che viene inviato insieme a un messaggio per garantire l'autenticazione del messaggio.

Il processo di utilizzo del MAC per l'autenticazione è illustrato nella figura seguente:

In Java il Mac classe di javax.cryptopacchetto fornisce la funzionalità del codice di autenticazione del messaggio. Seguire i passaggi indicati di seguito per creare il codice di autenticazione del messaggio utilizzando questa classe.

Passaggio 1: crea un oggetto KeyGenerator

Il KeyGenerator classe fornisce getInstance() che accetta una variabile String che rappresenta l'algoritmo di generazione della chiave richiesto e restituisce un file KeyGenerator oggetto che genera chiavi segrete.

Creare KeyGenerator oggetto utilizzando il getInstance() metodo come mostrato di seguito.

//Creating a KeyGenerator object
KeyGenerator keyGen = KeyGenerator.getInstance("DES");

Passaggio 2: crea l'oggetto SecureRandom

Il SecureRandom classe di java.SecurityIl pacchetto fornisce un potente generatore di numeri casuali che viene utilizzato per generare numeri casuali in Java. Istanziare questa classe come mostrato di seguito.

//Creating a SecureRandom object
SecureRandom secRandom = new SecureRandom();

Passaggio 3: inizializza KeyGenerator

Il KeyGenerator class fornisce un metodo denominato init() questo metodo accetta il SecureRandom oggetto e inizializza la corrente KeyGenerator.

Inizializza l'oggetto KeyGenerator creato nel passaggio precedente utilizzando questo metodo.

//Initializing the KeyGenerator
keyGen.init(secRandom);

Passaggio 4: genera la chiave

Genera la chiave usando generateKey() metodo del KeyGenerator classe come mostrato di seguito.

//Creating/Generating a key
Key key = keyGen.generateKey();

Passaggio 5: inizializza l'oggetto Mac

Il init() Il metodo della classe Mac accetta un oggetto Key e inizializza l'oggetto Mac corrente utilizzando la chiave specificata.

//Initializing the Mac object
mac.init(key);

Passaggio 6: completare l'operazione Mac

Il doFinal()metodo della classe Mac viene utilizzato per completare l'operazione Mac. Passare i dati richiesti sotto forma di array di byte a questo metodo e completare l'operazione come mostrato di seguito.

//Computing the Mac
String msg = new String("Hi how are you");
byte[] bytes = msg.getBytes();
byte[] macResult = mac.doFinal(bytes);

Esempio

L'esempio seguente mostra la generazione del codice MAC (Message Authentication Code) utilizzando JCA. Qui, prendiamo un semplice messaggio "Ciao come stai" e generiamo un Mac per quel messaggio.

import java.security.Key;
import java.security.SecureRandom;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;

public class MacSample {
   public static void main(String args[]) throws Exception{
      //Creating a KeyGenerator object
      KeyGenerator keyGen = KeyGenerator.getInstance("DES");

      //Creating a SecureRandom object
      SecureRandom secRandom = new SecureRandom();

      //Initializing the KeyGenerator
      keyGen.init(secRandom);

      //Creating/Generating a key
      Key key = keyGen.generateKey();	 

      //Creating a Mac object
      Mac mac = Mac.getInstance("HmacSHA256");

      //Initializing the Mac object
      mac.init(key);

      //Computing the Mac
      String msg = new String("Hi how are you");
      byte[] bytes = msg.getBytes();      
      byte[] macResult = mac.doFinal(bytes);

      System.out.println("Mac result:");
      System.out.println(new String(macResult));     
   }
}

Produzione

Il programma precedente genererà il seguente output:

Mac result:
HÖ„^ǃÎ_Utbh…?š_üzØSSÜh_ž_œa0ŽV?

Un sistema crittografico è un'implementazione di tecniche crittografiche e della relativa infrastruttura per fornire servizi di sicurezza delle informazioni. Un criptosistema è anche indicato come uncipher system.

I vari componenti di un crittosistema di base sono Plaintext, Encryption Algorithm, Ciphertext, Decryption Algorithm, Chiave di crittografia e, Chiave di decrittografia.

Dove,

  • Encryption Keyè un valore noto al mittente. Il mittente inserisce la chiave di crittografia nell'algoritmo di crittografia insieme al testo in chiaro per calcolare il testo cifrato.

  • Decryption Keyè un valore noto al destinatario. La chiave di decrittografia è correlata alla chiave di crittografia, ma non è sempre identica ad essa. Il ricevitore inserisce la chiave di decrittazione nell'algoritmo di decrittazione insieme al testo cifrato per calcolare il testo in chiaro.

Fondamentalmente esistono due tipi di chiavi / sistemi crittografici basati sul tipo di algoritmi di crittografia-decrittografia.

Crittografia a chiave simmetrica

Il processo di crittografia dove same keys are used for encrypting and decrypting le informazioni sono note come Symmetric Key Encryption.

Lo studio dei criptosistemi simmetrici è indicato come symmetric cryptography. I sistemi crittografici simmetrici sono talvolta indicati anche comesecret key cryptosystems.

Di seguito sono riportati alcuni esempi comuni di crittografia a chiave simmetrica:

  • Standard di crittografia digitale (DES)
  • Triple-DES (3DES)
  • IDEA
  • BLOWFISH

Crittografia della chiave asimmetrica

Il processo di crittografia dove different keys are used for encrypting and decrypting the informationè noto come Asymmetric Key Encryption. Sebbene le chiavi siano diverse, sono matematicamente correlate e quindi è possibile recuperare il testo in chiaro decrittografando il testo cifrato.

Le chiavi e i certificati utilizzati / generati vengono archiviati in un database denominato keystore. Per impostazione predefinita, questo database è archiviato in un file denominato.keystore.

È possibile accedere ai contenuti di questo database utilizzando il KeyStore classe di java.securitypacchetto. Questo gestisce tre diverse voci, ovvero PrivateKeyEntry, SecretKeyEntry, TrustedCertificateEntry.

  • PrivateKeyEntry
  • SecretKeyEntry
  • TrustedCertificateEntry

Memorizzazione di una chiave nel keystore

In questa sezione impareremo come memorizzare una chiave in un keystore. Per memorizzare una chiave nel keystore, seguire i passaggi indicati di seguito.

Passaggio 1: creare un oggetto KeyStore

Il getInstance() metodo del KeyStore classe di java.security package accetta un valore stringa che rappresenta il tipo di keystore e restituisce un oggetto KeyStore.

Crea un oggetto della classe KeyStore utilizzando il getInstance() metodo come mostrato di seguito.

//Creating the KeyStore object
KeyStore keyStore = KeyStore.getInstance("JCEKS");

Passaggio 2: caricare l'oggetto KeyStore

Il load() Il metodo della classe KeyStore accetta un oggetto FileInputStream che rappresenta il file del keystore e un parametro String che specifica la password del KeyStore.

In generale, il KeyStore è memorizzato nel file denominato cacerts, nella posizione C:/Program Files/Java/jre1.8.0_101/lib/security/ e la sua password predefinita è changeit, caricalo utilizzando il file load() metodo come mostrato di seguito.

//Loading the KeyStore object
char[] password = "changeit".toCharArray();
String path = "C:/Program Files/Java/jre1.8.0_101/lib/security/cacerts";
java.io.FileInputStream fis = new FileInputStream(path);
keyStore.load(fis, password);

Passaggio 3: creare l'oggetto KeyStore.ProtectionParameter

Istanziare il KeyStore.ProtectionParameter come mostrato di seguito.

//Creating the KeyStore.ProtectionParameter object
KeyStore.ProtectionParameter protectionParam = new KeyStore.PasswordProtection(password);

Passaggio 4: creare un oggetto SecretKey

Crea il file SecretKey oggetto (interfaccia) istanziando la sua classe Sub SecretKeySpec. Durante la creazione dell'istanza è necessario passare password e algoritmo come parametri al suo costruttore come mostrato di seguito.

//Creating SecretKey object
SecretKey mySecretKey = new SecretKeySpec(new String(keyPassword).getBytes(), "DSA");

Passaggio 5: creare un oggetto SecretKeyEntry

Crea un oggetto di SecretKeyEntry class passando il SecretKey oggetto creato nel passaggio precedente come mostrato di seguito.

//Creating SecretKeyEntry object
KeyStore.SecretKeyEntry secretKeyEntry = new KeyStore.SecretKeyEntry(mySecretKey);

Passaggio 6: impostare una voce nel KeyStore

Il setEntry() metodo del KeyStore class accetta un parametro String che rappresenta l'alias della voce del keystore, a SecretKeyEntry object, un oggetto ProtectionParameter e, memorizza la voce con l'alias specificato.

Impostare la voce nel keystore utilizzando il setEntry() metodo come mostrato di seguito.

//Set the entry to the keystore
keyStore.setEntry("secretKeyAlias", secretKeyEntry, protectionParam);

Example

L'esempio seguente memorizza le chiavi nel keystore esistente nel file "cacerts" (sistema operativo Windows 10).

import java.io.FileInputStream;
import java.security.KeyStore;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class StoringIntoKeyStore{
   public static void main(String args[]) throws Exception {
      //Creating the KeyStore object
      KeyStore keyStore = KeyStore.getInstance("JCEKS");

      //Loading the KeyStore object
      char[] password = "changeit".toCharArray();
      String path = "C:/Program Files/Java/jre1.8.0_101/lib/security/cacerts";
      java.io.FileInputStream fis = new FileInputStream(path);
      keyStore.load(fis, password);
      
      //Creating the KeyStore.ProtectionParameter object
      KeyStore.ProtectionParameter protectionParam = new KeyStore.PasswordProtection(password);

      //Creating SecretKey object
      SecretKey mySecretKey = new SecretKeySpec("myPassword".getBytes(), "DSA");
      
      //Creating SecretKeyEntry object
      KeyStore.SecretKeyEntry secretKeyEntry = new KeyStore.SecretKeyEntry(mySecretKey);
      keyStore.setEntry("secretKeyAlias", secretKeyEntry, protectionParam);

      //Storing the KeyStore object
      java.io.FileOutputStream fos = null;
      fos = new java.io.FileOutputStream("newKeyStoreName");
      keyStore.store(fos, password);
      System.out.println("data stored");
   }
}

Output

Il programma di cui sopra genera il seguente output:

System.out.println("data stored");

In questo capitolo impareremo come recuperare una chiave dal keystore utilizzando Java Cryptography.

Per recuperare una chiave dal keystore, seguire i passaggi indicati di seguito.

Passaggio 1: creare un oggetto KeyStore

Il getInstance() metodo del KeyStore classe di java.security package accetta un valore stringa che rappresenta il tipo di keystore e restituisce un oggetto KeyStore.

Crea un oggetto della classe KeyStore utilizzando questo metodo come mostrato di seguito.

//Creating the KeyStore object
KeyStore keyStore = KeyStore.getInstance("JCEKS");

Passaggio 2: caricare l'oggetto KeyStore

Il load() metodo della classe KeyStore accetta un file FileInputStream oggetto che rappresenta il file keystore e un parametro String che specifica la password del KeyStore.

In generale, il KeyStore è memorizzato nel file denominato cacerts, nella posizione C:/Program Files/Java/jre1.8.0_101/lib/security/ e la sua password predefinita è changeit, caricalo utilizzando il file load() metodo come mostrato di seguito.

//Loading the KeyStore object
char[] password = "changeit".toCharArray();
String path = "C:/Program Files/Java/jre1.8.0_101/lib/security/cacerts";
java.io.FileInputStream fis = new FileInputStream(path);
keyStore.load(fis, password);

Passaggio 3: creare l'oggetto KeyStore.ProtectionParameter

Istanziare il KeyStore.ProtectionParameter come mostrato di seguito.

//Creating the KeyStore.ProtectionParameter object
KeyStore.ProtectionParameter protectionParam = new KeyStore.PasswordProtection(password);

Passaggio 4: creare un oggetto SecretKey

Crea il file SecretKey oggetto (interfaccia) istanziando la sua classe Sub SecretKeySpec. Durante la creazione dell'istanza è necessario passare password e algoritmo come parametri al suo costruttore come mostrato di seguito.

//Creating SecretKey object
SecretKey mySecretKey = new SecretKeySpec(new String(keyPassword).getBytes(), "DSA");

Passaggio 5: creare un oggetto SecretKeyEntry

Crea un oggetto di SecretKeyEntry class passando il SecretKey oggetto creato nel passaggio precedente come mostrato di seguito.

//Creating SecretKeyEntry object
KeyStore.SecretKeyEntry secretKeyEntry = new KeyStore.SecretKeyEntry(mySecretKey);

Passaggio 6: impostare una voce nel KeyStore

Il setEntry() metodo del KeyStore class accetta un parametro String che rappresenta l'alias della voce del keystore, a SecretKeyEntry object, un oggetto ProtectionParameter e, memorizza la voce con l'alias specificato.

Impostare la voce nel keystore utilizzando il setEntry() metodo come mostrato di seguito.

//Set the entry to the keystore
keyStore.setEntry("secretKeyAlias", secretKeyEntry, protectionParam);

Passaggio 7: creare l'oggetto KeyStore.SecretKeyEntry

Il getEntry() metodo della classe KeyStore accetta un alias (parametro String) e un oggetto della classe ProtectionParameter come parametri e restituisce un KeyStoreEntry oggetto, quindi puoi lanciarlo in esso KeyStore.SecretKeyEntry oggetto.

Creare un oggetto della classe KeyStore.SecretKeyEntry passando l'alias per la chiave richiesta e l'oggetto del parametro di protezione creato nei passaggi precedenti, al getEntry() metodo come mostrato di seguito.

//Creating the KeyStore.SecretKeyEntry object
KeyStore.SecretKeyEntry secretKeyEnt = (KeyStore.SecretKeyEntry)keyStore.getEntry("secretKeyAlias", protectionParam);

Passaggio 8: creare l'oggetto chiave della voce recuperata

Il getSecretKey() metodo del SecretKeyEntryclass restituisce un oggetto SecretKey. Utilizzando questo metodo creare un oggetto SecretKey come mostrato di seguito.

//Creating SecretKey object
SecretKey mysecretKey = secretKeyEnt.getSecretKey();      
System.out.println(mysecretKey);

Esempio

L'esempio seguente mostra come recuperare le chiavi da un archivio chiavi. Qui, memorizziamo una chiave in un keystore, che si trova nel file "cacerts" (sistema operativo Windows 10), la recuperiamo e visualizziamo alcune delle sue proprietà come l'algoritmo utilizzato per generare la chiave e, il formato la chiave recuperata.

import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.KeyStore.ProtectionParameter;
import java.security.KeyStore.SecretKeyEntry;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class RetrievingFromKeyStore{
   public static void main(String args[]) throws Exception{
      //Creating the KeyStore object
      KeyStore keyStore = KeyStore.getInstance("JCEKS");

      //Loading the the KeyStore object
      char[] password = "changeit".toCharArray();
      java.io.FileInputStream fis = new FileInputStream(
         "C:/Program Files/Java/jre1.8.0_101/lib/security/cacerts");
      
      keyStore.load(fis, password);
      
      //Creating the KeyStore.ProtectionParameter object
      ProtectionParameter protectionParam = new KeyStore.PasswordProtection(password);

      //Creating SecretKey object
      SecretKey mySecretKey = new SecretKeySpec("myPassword".getBytes(), "DSA");
      
      //Creating SecretKeyEntry object
      SecretKeyEntry secretKeyEntry = new SecretKeyEntry(mySecretKey);
      keyStore.setEntry("secretKeyAlias", secretKeyEntry, protectionParam);

      //Storing the KeyStore object
      java.io.FileOutputStream fos = null;
      fos = new java.io.FileOutputStream("newKeyStoreName");
      keyStore.store(fos, password);
      
      //Creating the KeyStore.SecretKeyEntry object
      SecretKeyEntry secretKeyEnt = (SecretKeyEntry)keyStore.getEntry("secretKeyAlias", protectionParam);

      //Creating SecretKey object
      SecretKey mysecretKey = secretKeyEnt.getSecretKey();      
      System.out.println("Algorithm used to generate key : "+mysecretKey.getAlgorithm());   
      System.out.println("Format used for the key: "+mysecretKey.getFormat());
   }
}

Produzione

Il programma di cui sopra genera il seguente output:

Algorithm used to generate key: DSA
Format of the key: RAW

Java fornisce KeyGenerator classe questa classe viene utilizzata per generare chiavi segrete e gli oggetti di questa classe sono riutilizzabili.

Per generare chiavi utilizzando la classe KeyGenerator seguire i passaggi indicati di seguito.

Passaggio 1: crea un oggetto KeyGenerator

Il KeyGenerator classe fornisce getInstance() che accetta una variabile String che rappresenta l'algoritmo di generazione della chiave richiesto e restituisce un oggetto KeyGenerator che genera chiavi segrete.

Creare KeyGenerator oggetto utilizzando il getInstance() metodo come mostrato di seguito.

//Creating a KeyGenerator object
KeyGenerator keyGen = KeyGenerator.getInstance("DES");

Passaggio 2: crea l'oggetto SecureRandom

Il SecureRandom classe di java.SecurityIl pacchetto fornisce un potente generatore di numeri casuali che viene utilizzato per generare numeri casuali in Java. Istanziare questa classe come mostrato di seguito.

//Creating a SecureRandom object
SecureRandom secRandom = new SecureRandom();

Passaggio 3: inizializza KeyGenerator

Il KeyGenerator class fornisce un metodo denominato init() questo metodo accetta l'oggetto SecureRandom e inizializza il file current KeyGenerator.

Inizializza l'oggetto KeyGenerator creato nel passaggio precedente utilizzando il init() metodo.

//Initializing the KeyGenerator
keyGen.init(secRandom);

Esempio

L'esempio seguente mostra la generazione della chiave della chiave segreta utilizzando la classe KeyGenerator di javax.crypto pacchetto.

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;

import java.security.Key;
import java.security.SecureRandom;

public class KeyGeneratorExample {
   public static void main(String args[]) throws Exception{
      //Creating a KeyGenerator object
      KeyGenerator keyGen = KeyGenerator.getInstance("DES");
      
      //Creating a SecureRandom object
      SecureRandom secRandom = new SecureRandom();
      
      //Initializing the KeyGenerator
      keyGen.init(secRandom);
      
      //Creating/Generating a key
      Key key = keyGen.generateKey();
      
      System.out.println(key);      
      Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");      
      cipher.init(cipher.ENCRYPT_MODE, key);      

      String msg = new String("Hi how are you");
      byte[] bytes = cipher.doFinal(msg.getBytes());      
      System.out.println(bytes);      
   }
}

Produzione

Il programma di cui sopra genera il seguente output:

com.sun.crypto.provider.DESKey@18629
[B@2ac1fdc4

Java fornisce l'estensione KeyPairGeneratorclasse. Questa classe viene utilizzata per generare coppie di chiavi pubbliche e private. Per generare chiavi utilizzando ilKeyPairGenerator classe, seguire i passaggi indicati di seguito.

Passaggio 1: crea un oggetto KeyPairGenerator

Il KeyPairGenerator classe fornisce getInstance() che accetta una variabile String che rappresenta l'algoritmo di generazione delle chiavi richiesto e restituisce un oggetto KeyPairGenerator che genera le chiavi.

Creare KeyPairGenerator oggetto utilizzando il getInstance() metodo come mostrato di seguito.

//Creating KeyPair generator object
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DSA");

Passaggio 2: inizializza l'oggetto KeyPairGenerator

Il KeyPairGenerator class fornisce un metodo denominato initialize()questo metodo viene utilizzato per inizializzare il generatore di coppie di chiavi. Questo metodo accetta un valore intero che rappresenta la dimensione della chiave.

Inizializza l'oggetto KeyPairGenerator creato nel passaggio precedente utilizzando questo metodo come mostrato di seguito.

//Initializing the KeyPairGenerator
keyPairGen.initialize(2048);

Passaggio 3: genera il KeyPairGenerator

Puoi generare il file KeyPair usando il generateKeyPair() metodo del KeyPairGeneratorclasse. Genera la coppia di chiavi utilizzando questo metodo come mostrato di seguito.

//Generate the pair of keys
KeyPair pair = keyPairGen.generateKeyPair();

Passaggio 4: ottieni la chiave privata / chiave pubblica

È possibile ottenere la chiave privata dall'oggetto KeyPair generato utilizzando il getPrivate() metodo come mostrato di seguito.

//Getting the private key from the key pair
PrivateKey privKey = pair.getPrivate();

È possibile ottenere la chiave pubblica dall'oggetto KeyPair generato utilizzando il getPublic() metodo come mostrato di seguito.

//Getting the public key from the key pair
PublicKey publicKey = pair.getPublic();

Esempio

L'esempio seguente mostra la generazione della chiave della chiave segreta utilizzando la classe KeyPairGenerator di javax.crypto pacchetto.

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;

public class KeyPairGenertor {
   public static void main(String args[]) throws Exception{
      //Creating KeyPair generator object
      KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DSA");
      
      //Initializing the KeyPairGenerator
      keyPairGen.initialize(2048);
      
      //Generating the pair of keys
      KeyPair pair = keyPairGen.generateKeyPair();
      
      //Getting the private key from the key pair
      PrivateKey privKey = pair.getPrivate();   
      
      //Getting the public key from the key pair
      PublicKey publicKey = pair.getPublic(); 
      System.out.println("Keys generated");
   }
}

Produzione

Il programma di cui sopra genera il seguente output:

Keys generated

Le firme digitali ci consentono di verificare l'autore, la data e l'ora delle firme, autenticare il contenuto del messaggio. Include anche la funzione di autenticazione per funzionalità aggiuntive.

Vantaggi della firma digitale

In questa sezione, apprenderemo i diversi motivi che richiedono l'uso della firma digitale. Ci sono diversi motivi per implementare le firme digitali nelle comunicazioni:

Autenticazione

Le firme digitali aiutano ad autenticare le origini dei messaggi. Ad esempio, se la filiale di una banca invia un messaggio all'ufficio centrale, richiedendo la modifica del saldo di un conto. Se l'ufficio centrale non è in grado di autenticare il messaggio inviato da una fonte autorizzata, agire su tale richiesta potrebbe essere un grave errore.

Integrità

Una volta che il messaggio è stato firmato, qualsiasi modifica nel messaggio invaliderebbe la firma.

Non ripudio

Per questa proprietà, qualsiasi entità che abbia firmato alcune informazioni non può in un secondo momento negare di averle firmate.

Creazione della firma digitale

Impariamo ora come creare una firma digitale. È possibile creare una firma digitale utilizzando Java seguendo i passaggi indicati di seguito.

Passaggio 1: crea un oggetto KeyPairGenerator

Il KeyPairGenerator classe fornisce getInstance() che accetta una variabile String che rappresenta l'algoritmo di generazione delle chiavi richiesto e restituisce un oggetto KeyPairGenerator che genera le chiavi.

Creare KeyPairGenerator oggetto utilizzando il getInstance() metodo come mostrato di seguito.

//Creating KeyPair generator object
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DSA");

Passaggio 2: inizializza l'oggetto KeyPairGenerator

Il KeyPairGenerator class fornisce un metodo denominato initialize()questo metodo viene utilizzato per inizializzare il generatore di coppie di chiavi. Questo metodo accetta un valore intero che rappresenta la dimensione della chiave.

Inizializza l'oggetto KeyPairGenerator creato nel passaggio precedente utilizzando l'estensione initialize() metodo come mostrato di seguito.

//Initializing the KeyPairGenerator
keyPairGen.initialize(2048);

Passaggio 3: genera il KeyPairGenerator

Puoi generare il file KeyPair usando il generateKeyPair()metodo. Genera la coppia di chiavi utilizzando ilgenerateKeyPair() metodo come mostrato di seguito.

//Generate the pair of keys
KeyPair pair = keyPairGen.generateKeyPair();

Passaggio 4: ottieni la chiave privata dalla coppia

È possibile ottenere la chiave privata dall'oggetto KeyPair generato utilizzando il getPrivate() metodo.

Ottieni la chiave privata utilizzando il getPrivate() metodo come mostrato di seguito.

//Getting the private key from the key pair
PrivateKey privKey = pair.getPrivate();

Passaggio 5: crea un oggetto firma

Il getInstance() metodo del Signature class accetta un parametro stringa che rappresenta l'algoritmo di firma richiesto e restituisce il rispettivo oggetto Signature.

Crea un oggetto della classe Signature utilizzando il file getInstance() metodo.

//Creating a Signature object
Signature sign = Signature.getInstance("SHA256withDSA");

Passaggio 6: inizializza l'oggetto Firma

Il initSign() metodo della classe Signature accetta un file PrivateKey object e inizializza l'oggetto Signature corrente.

Inizializza l'oggetto Firma creato nel passaggio precedente utilizzando il file initSign() metodo come mostrato di seguito.

//Initialize the signature
sign.initSign(privKey);

Passaggio 7: aggiungere dati all'oggetto Firma

Il update() Il metodo della classe Signature accetta un array di byte che rappresenta i dati da firmare o verificare e aggiorna l'oggetto corrente con i dati forniti.

Aggiorna l'oggetto Signature inizializzato passando i dati da firmare al file update() metodo sotto forma di array di byte come mostrato di seguito.

byte[] bytes = "Hello how are you".getBytes();      

//Adding data to the signature
sign.update(bytes);

Passaggio 8: calcolare la firma

Il sign() metodo del Signature class restituisce i byte di firma dei dati aggiornati.

Calcola la firma utilizzando il sign() metodo come mostrato di seguito.

//Calculating the signature
byte[] signature = sign.sign();

Example

Il seguente programma Java accetta un messaggio dall'utente e genera una firma digitale per il messaggio specificato.

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.Signature;
import java.util.Scanner;

public class CreatingDigitalSignature {
   public static void main(String args[]) throws Exception {
      //Accepting text from user
      Scanner sc = new Scanner(System.in);
      System.out.println("Enter some text");
      String msg = sc.nextLine();
      
      //Creating KeyPair generator object
      KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DSA");
      
      //Initializing the key pair generator
      keyPairGen.initialize(2048);
      
      //Generate the pair of keys
      KeyPair pair = keyPairGen.generateKeyPair();
      
      //Getting the private key from the key pair
      PrivateKey privKey = pair.getPrivate();
      
      //Creating a Signature object
      Signature sign = Signature.getInstance("SHA256withDSA");
      
      //Initialize the signature
      sign.initSign(privKey);
      byte[] bytes = "msg".getBytes();
      
      //Adding data to the signature
      sign.update(bytes);
      
      //Calculating the signature
      byte[] signature = sign.sign();
      
      //Printing the signature
      System.out.println("Digital signature for given text: "+new String(signature, "UTF8"));
   }
}

Output

Il programma di cui sopra genera il seguente output:

Enter some text
Hi how are you
Digital signature for given text: 0=@gRD???-?.???? /yGL?i??a!?

È possibile creare una firma digitale utilizzando Java e verificarla seguendo i passaggi indicati di seguito.

Passaggio 1: crea un oggetto KeyPairGenerator

Il KeyPairGenerator classe fornisce getInstance() che accetta una variabile String che rappresenta l'algoritmo di generazione delle chiavi richiesto e restituisce un oggetto KeyPairGenerator che genera le chiavi.

Creare KeyPairGenerator oggetto utilizzando il getInstance() metodo come mostrato di seguito.

//Creating KeyPair generator object
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DSA");

Passaggio 2: inizializza l'oggetto KeyPairGenerator

Il KeyPairGenerator class fornisce un metodo denominato initialize()metodo. Questo metodo viene utilizzato per inizializzare il generatore di coppie di chiavi. Questo metodo accetta un valore intero che rappresenta la dimensione della chiave.

Inizializza l'oggetto KeyPairGenerator creato nel passaggio precedente utilizzando l'estensione initialize() metodo come mostrato di seguito.

//Initializing the KeyPairGenerator
keyPairGen.initialize(2048);

Passaggio 3: genera il KeyPairGenerator

Puoi generare il file KeyPair usando il generateKeyPair()metodo. Genera la coppia di chiavi utilizzando questo metodo come mostrato di seguito.

//Generate the pair of keys
KeyPair pair = keyPairGen.generateKeyPair();

Passaggio 4: ottieni la chiave privata dalla coppia

È possibile ottenere la chiave privata dall'oggetto KeyPair generato utilizzando il getPrivate() metodo.

Ottieni la chiave privata utilizzando il getPrivate() metodo come mostrato di seguito.

//Getting the private key from the key pair
PrivateKey privKey = pair.getPrivate();

Passaggio 5: crea un oggetto firma

Il getInstance() metodo del Signature class accetta un parametro stringa che rappresenta l'algoritmo di firma richiesto e restituisce il rispettivo oggetto Signature.

Crea un oggetto della classe Signature utilizzando il file getInstance() metodo.

//Creating a Signature object
Signature sign = Signature.getInstance("SHA256withDSA");

Passaggio 6: inizializza l'oggetto Firma

Il initSign() metodo della classe Signature accetta un file PrivateKey object e inizializza l'oggetto Signature corrente.

Inizializza l'oggetto Firma creato nel passaggio precedente utilizzando il file initSign() metodo come mostrato di seguito.

//Initialize the signature
sign.initSign(privKey);

Passaggio 7: aggiungere dati all'oggetto Firma

Il update() Il metodo della classe Signature accetta un array di byte che rappresenta i dati da firmare o verificare e aggiorna l'oggetto corrente con i dati forniti.

Aggiorna l'oggetto Signature inizializzato passando i dati da firmare al file update() metodo sotto forma di array di byte come mostrato di seguito.

byte[] bytes = "Hello how are you".getBytes();      

//Adding data to the signature
sign.update(bytes);

Passaggio 8: calcolare la firma

Il sign() metodo del Signature class restituisce i byte di firma dei dati aggiornati.

Calcola la firma utilizzando il metodo sign () come mostrato di seguito.

//Calculating the signature
byte[] signature = sign.sign();

Passaggio 9: inizializza l'oggetto firma per la verifica

Per verificare un oggetto Signature è necessario inizializzarlo prima utilizzando il initVerify() metodo it metodo accetta a PublicKey oggetto.

Pertanto, inizializza l'oggetto Signature per la verifica utilizzando il file initVerify() metodo come mostrato di seguito.

//Initializing the signature
sign.initVerify(pair.getPublic());

Passaggio 10: aggiorna i dati da verificare

Aggiorna l'oggetto inizializzato (per la verifica) con i dati da verificare utilizzando il metodo di aggiornamento come mostrato di seguito.

//Update the data to be verified
sign.update(bytes);

Passaggio 11: verifica la firma

Il verify()Il metodo della classe Signature accetta un altro oggetto firma e lo verifica con quello corrente. Se si verifica una corrispondenza, restituisce true altrimenti restituisce false.

Verificare la firma utilizzando questo metodo come mostrato di seguito.

//Verify the signature
boolean bool = sign.verify(signature);

Esempio

Il seguente programma Java accetta un messaggio dall'utente, genera una firma digitale per il messaggio dato e lo verifica.

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.Signature;

import java.util.Scanner;

public class SignatureVerification {
   public static void main(String args[]) throws Exception{
      //Creating KeyPair generator object
      KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DSA");
	      
      //Initializing the key pair generator
      keyPairGen.initialize(2048);
	      
      //Generate the pair of keys
      KeyPair pair = keyPairGen.generateKeyPair();
      
      //Getting the privatekey from the key pair
      PrivateKey privKey = pair.getPrivate();

      //Creating a Signature object
      Signature sign = Signature.getInstance("SHA256withDSA");

      //Initializing the signature
      sign.initSign(privKey);
      byte[] bytes = "Hello how are you".getBytes();
      
      //Adding data to the signature
      sign.update(bytes);
      
      //Calculating the signature
      byte[] signature = sign.sign();      
      
      //Initializing the signature
      sign.initVerify(pair.getPublic());
      sign.update(bytes);
      
      //Verifying the signature
      boolean bool = sign.verify(signature);
      
      if(bool) {
         System.out.println("Signature verified");   
      } else {
         System.out.println("Signature failed");
      }
   }
}

Produzione

Il programma di cui sopra genera il seguente output:

Signature verified

È possibile crittografare i dati forniti utilizzando la classe Cipher di javax.cryptopacchetto. Seguire i passaggi indicati di seguito per crittografare i dati forniti utilizzando Java.

Passaggio 1: crea un oggetto KeyPairGenerator

Il KeyPairGenerator classe fornisce getInstance() che accetta una variabile String che rappresenta l'algoritmo di generazione delle chiavi richiesto e restituisce un oggetto KeyPairGenerator che genera le chiavi.

Creare KeyPairGenerator oggetto utilizzando il getInstance() metodo come mostrato di seguito.

//Creating KeyPair generator object
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DSA");

Passaggio 2: inizializza l'oggetto KeyPairGenerator

Il KeyPairGenerator class fornisce un metodo denominato initialize()questo metodo viene utilizzato per inizializzare il generatore di coppie di chiavi. Questo metodo accetta un valore intero che rappresenta la dimensione della chiave.

Inizializza l'oggetto KeyPairGenerator creato nel passaggio precedente utilizzando l'estensione initialize() metodo come mostrato di seguito.

//Initializing the KeyPairGenerator
keyPairGen.initialize(2048);

Passaggio 3: genera il KeyPairGenerator

Puoi generare il file KeyPair usando il generateKeyPair() metodo del KeyPairGeneratorclasse. Genera la coppia di chiavi utilizzando questo metodo come mostrato di seguito.

//Generate the pair of keys
KeyPair pair = keyPairGen.generateKeyPair();

Passaggio 4: ottieni la chiave pubblica

Puoi ottenere la chiave pubblica dal file KeyPair oggetto utilizzando il getPublic() metodo come mostrato di seguito.

Ottieni la chiave pubblica utilizzando questo metodo come mostrato di seguito.

//Getting the public key from the key pair
PublicKey publicKey = pair.getPublic();

Passaggio 5: creare un oggetto Cipher

Il getInstance() metodo di Cipher class accetta una variabile String che rappresenta la trasformazione richiesta e restituisce un oggetto Cipher che implementa la trasformazione data.

Crea l'oggetto Cipher usando il getInstance() metodo come mostrato di seguito.

//Creating a Cipher object
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

Passaggio 6: inizializza l'oggetto Cipher

Il init() metodo del Cipher class accetta due parametri un parametro intero che rappresenta la modalità di funzionamento (crittografia / decrittografia) e un oggetto Key che rappresenta la chiave pubblica.

Inizializza l'oggetto Cypher utilizzando il init() metodo come mostrato di seguito.

//Initializing a Cipher object
cipher.init(Cipher.ENCRYPT_MODE, publicKey);

Passaggio 7: aggiungere dati all'oggetto Cipher

Il update() Il metodo della classe Cipher accetta un array di byte che rappresenta i dati da crittografare e aggiorna l'oggetto corrente con i dati forniti.

Aggiorna l'oggetto Cipher inizializzato passando i dati al file update() metodo sotto forma di array di byte come mostrato di seguito.

//Adding data to the cipher
byte[] input = "Welcome to Tutorialspoint".getBytes();	  
cipher.update(input);

Passaggio 8: crittografa i dati

Il doFinal()metodo della classe Cipher completa l'operazione di crittografia. Pertanto, completare la crittografia utilizzando questo metodo come mostrato di seguito.

//Encrypting the data
byte[] cipherText = cipher.doFinal();

Esempio

Il seguente programma Java accetta testo dall'utente, lo crittografa utilizzando l'algoritmo RSA e stampa il formato crittografato del testo specificato.

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;

public class CipherSample {
   public static void main(String args[]) throws Exception{
      //Creating a Signature object
      Signature sign = Signature.getInstance("SHA256withRSA");
      
      //Creating KeyPair generator object
      KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
      
      //Initializing the key pair generator
      keyPairGen.initialize(2048);
      
      //Generating the pair of keys
      KeyPair pair = keyPairGen.generateKeyPair();      
	
      //Creating a Cipher object
      Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        
      //Initializing a Cipher object
      cipher.init(Cipher.ENCRYPT_MODE, pair.getPublic());
	  
      //Adding data to the cipher
      byte[] input = "Welcome to Tutorialspoint".getBytes();	  
      cipher.update(input);
	  
      //encrypting the data
      byte[] cipherText = cipher.doFinal();	 
      System.out.println(new String(cipherText, "UTF8"));
   }
}

Produzione

Il programma di cui sopra genera il seguente output:

Encrypted Text: 
"???:]J_?]???;Xl??????*@??u???r??=T&???_?_??.??i?????(?$_f?zD??????ZGH??g??? g?E:_??bz^??f?~o???t?}??u=uzp\UI????Z??l[?G?3??Y?UAEfKT?f?O??N_?d__?????a_?15%?^? 'p?_?$,9"{??^??y??_?t???,?W?PCW??~??[?$??????e????f?Y-Zi__??_??w?_?&QT??`?`~?[?K_??_???

È possibile decrittografare i dati crittografati utilizzando la classe Cipher di javax.cryptopacchetto. Segui i passaggi indicati di seguito per decrittografare i dati utilizzando Java.

Passaggio 1: crea un oggetto KeyPairGenerator

Il KeyPairGenerator classe fornisce getInstance() che accetta una variabile String che rappresenta l'algoritmo di generazione delle chiavi richiesto e restituisce un oggetto KeyPairGenerator che genera le chiavi.

Creare KeyPairGenerator oggetto utilizzando il getInstance() metodo come mostrato di seguito.

//Creating KeyPair generator object
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DSA");

Passaggio 2: inizializza l'oggetto KeyPairGenerator

Il KeyPairGenerator class fornisce un metodo denominato initialize()questo metodo viene utilizzato per inizializzare il generatore di coppie di chiavi. Questo metodo accetta un valore intero che rappresenta la dimensione della chiave.

Inizializza l'oggetto KeyPairGenerator creato nel passaggio precedente utilizzando l'estensione initialize() metodo come mostrato di seguito.

//Initializing the KeyPairGenerator
keyPairGen.initialize(2048);

Passaggio 3: genera il KeyPairGenerator

Puoi generare il file KeyPair usando il generateKeyPair() metodo del KeyPairGeneratorclasse. Genera la coppia di chiavi utilizzando questo metodo come mostrato di seguito.

//Generate the pair of keys
KeyPair pair = keyPairGen.generateKeyPair();

Passaggio 4: ottieni la chiave pubblica

È possibile ottenere la chiave pubblica dall'oggetto KeyPair generato utilizzando il getPublic() metodo come mostrato di seguito.

//Getting the public key from the key pair
PublicKey publicKey = pair.getPublic();

Passaggio 5: creare un oggetto Cipher

Il getInstance() metodo di Cipher class accetta una variabile String che rappresenta la trasformazione richiesta e restituisce un oggetto Cipher che implementa la trasformazione data.

Crea l'oggetto Cipher usando il getInstance() metodo come mostrato di seguito.

//Creating a Cipher object
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

Passaggio 6: inizializza l'oggetto Cipher

Il init() metodo della classe Cipher accetta due parametri

  • Un parametro intero che rappresenta la modalità operativa (crittografia / decrittografia)
  • Oggetto chiave che rappresenta la chiave pubblica

Inizializza l'oggetto Cypher utilizzando il init() metodo come mostrato di seguito.

//Initializing a Cipher object
cipher.init(Cipher.ENCRYPT_MODE, publicKey);

Passaggio 7: aggiungere dati all'oggetto Cipher

Il update() Il metodo della classe Cipher accetta un array di byte che rappresenta i dati da crittografare e aggiorna l'oggetto corrente con i dati forniti.

Aggiorna l'oggetto Cipher inizializzato passando i dati al file update() metodo sotto forma di array di byte come mostrato di seguito.

//Adding data to the cipher
byte[] input = "Welcome to Tutorialspoint".getBytes();	  
cipher.update(input);

Passaggio 8: crittografa i dati

Il doFinal()metodo della classe Cipher completa l'operazione di crittografia. Pertanto, completare la crittografia utilizzando questo metodo come mostrato di seguito.

//Encrypting the data
byte[] cipherText = cipher.doFinal();

Passaggio 9: inizializza l'oggetto Cipher per la decrittografia

Per decrittografare la crittografia crittografata nei passaggi precedenti è necessario inizializzarla per la decrittografia.

Pertanto, inizializza l'oggetto di crittografia passando i parametri Cipher.DECRYPT_MODE e l'oggetto PrivateKey come mostrato di seguito.

//Initializing the same cipher for decryption
cipher.init(Cipher.DECRYPT_MODE, pair.getPrivate());

Passaggio 10: decrittografa i dati

Infine, decrittografa il testo crittografato utilizzando l'estensione doFinal() metodo come mostrato di seguito.

//Decrypting the text
byte[] decipheredText = cipher.doFinal(cipherText);

Esempio

Il seguente programma Java accetta il testo dell'utente, lo crittografa utilizzando l'algoritmo RSA e, stampa la cifra del testo dato, decrittografa la cifra e stampa nuovamente il testo decrittografato.

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;

import javax.crypto.Cipher;

public class CipherDecrypt {
   public static void main(String args[]) throws Exception{
	   //Creating a Signature object
      Signature sign = Signature.getInstance("SHA256withRSA");
      
      //Creating KeyPair generator object
      KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
      
      //Initializing the key pair generator
      keyPairGen.initialize(2048);
      
      //Generate the pair of keys
      KeyPair pair = keyPairGen.generateKeyPair();   
      
      //Getting the public key from the key pair
      PublicKey publicKey = pair.getPublic();  

      //Creating a Cipher object
      Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

      //Initializing a Cipher object
      cipher.init(Cipher.ENCRYPT_MODE, publicKey);
	  
      //Add data to the cipher
      byte[] input = "Welcome to Tutorialspoint".getBytes();	  
      cipher.update(input);
	  
      //encrypting the data
      byte[] cipherText = cipher.doFinal();	 
      System.out.println( new String(cipherText, "UTF8"));

      //Initializing the same cipher for decryption
      cipher.init(Cipher.DECRYPT_MODE, pair.getPrivate());
      
      //Decrypting the text
      byte[] decipheredText = cipher.doFinal(cipherText);
      System.out.println(new String(decipheredText));
   }
}

Produzione

Il programma di cui sopra genera il seguente output:

Encrypted Text:
]/[?F3?D?p
v?w?!?H???^?A??????P?u??FA?
?
???_?? ???_jMH-??>??OP?'?j?_?n`
?_??'`????o??_GL??g???g_f?????f|???LT?|?Vz_TDu#??\?<b,,?$C2???Bq?#?lDB`??g,^??K?_?v???`}
?;LX?a?_5e???#???_?6?/B&B_???^?__Ap^#_?q?IEh????_?,??*??]~_?_?D?
_y???lp??a?P_U{

Decrypted Text:
Welcome to Tutorialspoint