Cryptography & Java Internet Security 1 Goals of Network Security 2 Basic Cryptographic Concepts 3 Java Security Concepts & Applets 4 Java Cryptographic Architecture (JCE) & Java Cryptographic Extension (JCE) 5 An example: what students have to do ... 1 Goals of Network Security Security is multilateral ! • Confidentiality – symmetric encoding systems (bilateral) – asymmetric encoding systems (multilateral) – special protocols: S-HTTP, SSL, ... • Integrity – message digests, digital signatures (multilateral) – Message Autentification Code (MAC) • Availability – diversified networks • Commitment / attribute somebody something (requisition of services) – digital signatures (multilateral) Literature • Simon Singh The Code Book . The Science of Secrecy from Ancient Egypt to Quantum Cryptography Fourth Estate, London, 1999 in german: Geheime Botschaften. Die Kunst der Verschlüsselung von der Antike bis zum Internet. dtv, München 2001 Basics Cryptology = Cryptography + Crypto analysis Secret communication Cryptography Transposition Substitution Steganography 2 Basic Cryptographic Concepts • crypto system • cryptographically secure message digest (SHA-1, MD5, ...) • cryptographic cipher: encryption & decryption – symmetric encryption (DES, IDEA, ...) – asymmetric encryption (public key) (RSA, ElGamal, ...) • certificate (X.509 standard) • digital signatures: signing and verifying (DSA, RSA, ...) Crypto system M : plaintext space C : ciphertext space K : key space M : plaintext message C : ciphertext message K : key E = Encrypt D = Decrypt E(M )=C E:M× KC D(C )=M D:C× KM DK (EK (M) ) = M | M M Message Digest = one way hash function w = h (x) Example: w = bx (mod m) Message Authentification Code (MAC) = hash function with secure key w = h (x, k) Random number symmetric encryption k = secure key Key generator k ciphertext plaintext x encrypt C(x) plaintext decrypt x B A asymmetric encryption s = private key Key generator t = public key ciphertext plaintext x decrypt A C(x) plaintext encrypt B x Diffie-Hellman key exchange Public: g= 4, p=11 A Private key x A= 3 B Private key xB= 4 Public key yA= g xA mod p = 4 3 mod 11 = 64 mod 11 = 9 Public key yB= g xB mod p = 44 mod 11 = 256 mod 11 = 3 Session key K = yB xA mod p = 33 mod 11 = 5 K = yA xB mod p = 94 mod 11 = 5 X.509 Certificate version serial number Algorithm identifier Issuer (name of CA) Period of validity Subject (user name) Public key Signature (CA) Random number symmetric authentification k = secure key Key generator k Text with authentific. text x Generate MAC x, MAC Text, testresult test MAC x, {true | false} B A asymmetric authentication (signature system) s = private key (sign) Key generator t = public key (verify) text x Text with signature sign A x, sig(x) verify B Text with signatur + testresult x,sig(x), {true | false} 3 Java: Security Concept & Applets How an applet works and how it looks like A security manager in the JVM controls access • Java 1.0 Security Model – “Sandbox Model“ : no permission to access local resources (client) • Java 1.1 Security Model – signed applets introduced : full access to local resources – unsigned applets run in the sandbox • Java 1.2 Security Model Trouble: there are differences between appletviewer , Netscape, Microsoft IE in Java 1.1 and Java 1.2 Java 1.0 Security Model Java 1.1 Security Model Java 1.2 Security Model 4 Java Cryptographic Architecture (JCA) & Java Cryptographic Extension (JCE) • • Design principle: Provider - Algorithm - Concept Classes: SUN MD5 SHA1 MessageDigest X RSA DSA Signature Identity Signer MessageDigest Signature Key KeyPair KeyPairGenerator KeyGenerator SecureRamdom KeyStore Certificate X509Certificate Cipher 5 An example: what students have to do ... • • Task description for students steps: 1 give an applet rights to write a file belegis.dat on client 2 generate a keypair and a self signed certificate (X.509) ; store the keypair in a keystore file and export certificate to a file 3 write a Java-application that produces a MD5-Message Digest of file belegis.dat 4 write another Java-application that reads and signs the Java source code of step 3, concatenate the source with the signature and encrypt the result (symmetric cryptography). Deserialize a given session key for this purpose. • Store in a directory for verification (or send by Email): – file belegis.dat (load html-page) – the self signed certificate – the message digest – the chiffretext (use keytool) (run program of step 3) (run program of step 4) Preparation • Make available - applet BelegIS.java - HTML page BelegIS.html containing this applet • generate & make available (serialize) secure session key • generate keystore file c:\workstation\IS\mykeystore to include certificates come from students Solution • • • If no permissions are given to applet give file permissions by policytool applet writes belegis.dat now • generate a keystore file & a key pair by keytool, export certificate (step 2) • java source code (step 3) • java source code (step 4) Response to Solution Solution‘s Verification • register verification time • import certificate • • • • read keystore file verify message digest deserialize session key decrypt chiffretext and store temporary extract certificate proof validity of certificate prepare for verifying signature read signature verify signature • • • • • import java.security.*; import java.security.cert.*; import java.io.*; public class Beleg01Loes3{ public static void main(String args []){ try { FileInputStream fi = new FileInputStream("mykeystore"); KeyStore ks = KeyStore.getInstance("JKS","SUN"); char [] passwd1 = {'r','p','l','a','c','d','1'}; ks.load(fi,passwd1); char [] passwd2 = {'r','p','l','a','c','a','1'}; Key priv = ks.getKey("is_beleg",passwd2); MessageDigest md = MessageDigest.getInstance("MD5"); FileInputStream fi2 = new FileInputStream("c:/temp/belegis.dat"); byte xx =(byte)fi2.read(); while(xx != -1){ md.update(xx); xx =(byte)fi2.read(); } fi2.close(); System.out.println("------- Datei gelesen -------"); byte [] medi = md.digest(); FileOutputStream mdf = new FileOutputStream("belegis_MD5.dat"); mdf.write(medi); mdf.close(); System.out.println("---- MD5 geschrieben ----"); System.out.println("---------- ende ----------"); } catch(Exception e){ System.out.println("error:"+e); } } } import import import import import import import import java.io.*; java.security.*; java.security.spec.*; java.security.interfaces.*; java.security.cert.*; javax.crypto.*; javax.crypto.spec.*; javax.crypto.interfaces.*; public class Beleg01Loes4{ public static void main(String args[]){ try{ Provider sunJCE = new com.sun.crypto.provider.SunJCE(); Security.addProvider(sunJCE); System.out.println("Provider eingetragen"); File f1; File f2; if(args.length < 2) { System.out.println("Usage: java Beleg01Loes4 "+ " <plaintext file> <chiffretext file> "); System.exit(8); } f1 = new File(args[0]); f2 = new File(args[1]); FileInputStream fis; FileOutputStream fos; FileInputStream kfis; FileOutputStream kfos; fis = new FileInputStream(f1); fos = new FileOutputStream(f2); CipherInputStream cis; Cipher desciph = Cipher.getInstance("DES"); System.out.println("Cipher-Objekt erzeugt"); cis = new CipherInputStream(fis, desciph); SecretKey desKey; // Lesen und Signieren FileInputStream fi = new FileInputStream("mykeystore"); KeyStore ks = KeyStore.getInstance("JKS","SUN"); char [] passwd1 = {'r','p','l','a','c','d','1'}; ks.load(fi,passwd1); char [] passwd2 = {'r','p','l','a','c','a','1'}; Key priv = ks.getKey("bel",passwd2); Signature dsa = Signature.getInstance("DSA","SUN"); dsa.initSign((PrivateKey)priv); FileOutputStream mdfo = new FileOutputStream("beleg01_sig.dat"); int siz = (int) f1.length(); int z = 0; byte x =(byte)fis.read(); while(z < siz){ dsa.update(x); mdfo.write(x); z++; x =(byte)fis.read(); } byte [] sig = dsa.sign(); fis.close(); System.out.println("------- Datei gelesen und signiert -------"); mdfo.write((byte)'S'); mdfo.write((byte)'I'); mdfo.write((byte)'G'); System.out.println("------- SIG geschrieben -------"); mdfo.write(sig); mdfo.close(); System.out.println("------- signierte Datei geschrieben -------"); f1 = new File("beleg01_sig.dat"); fis = new FileInputStream(f1); cis = new CipherInputStream(fis, desciph); kfis = new FileInputStream( "i:/prakt/fritzsch/Sicherheit/chiffkey.dat"); ObjectInputStream keyin = new ObjectInputStream(kfis); desKey = (SecretKey)keyin.readObject(); System.out.println("Key deserialisiert"); desciph.init(Cipher.ENCRYPT_MODE,desKey); byte [] b = new byte [8]; int i = cis.read(b); while(i != -1){ fos.write(b,0,i); i = cis.read(b); } fos.close(); System.out.println("Dateien lesen/schreiben beendet"); } catch(Exception e){ System.err.println("Error:"+ e); } } } import import import import import java.security.*; java.security.cert.*; java.io.*; java.util.*; javax.crypto.*; public class Beleg01PruefS{ public static void main(String args []){ // Arbeitsverzeichnis: htw4711 // Aufruf: java Beleg01PruefS htw4711 try { // Zeitpunkt der Ueberpruefung registrieren ------------System.out.println("Beleg geprueft:"); System.out.println((new Date()).toLocaleString()); // Provider SunJCE eintragen ---------------------------Provider sunJCE = new com.sun.crypto.provider.SunJCE(); Security.addProvider(sunJCE); // Certificate löschen (auch wenn nicht vorhanden )---------String command1 = "keytool -delete " + " -alias " + args[0] + " -keystore i:/Prakt/fritzsch/Sicherheit/mykeystore“ + " -storepass rplacd1"; System.out.println("-- invoke: "); System.out.println(" " + command1); Runtime rt1 = Runtime.getRuntime(); Process p1 = rt1.exec(command1); p1.waitFor(); System.out.println(" ... beendet mit RC="+ p1.exitValue()); // Certificate importieren ----------------------------------System.out.println("-- Zertifikat importieren "); String command = "keytool -import "+ " -alias " + args[0] + " -file "+ args[0] + ".cer"+ //" -keystore c:/workstation/IS/mykeystore"+ " -keystore i:/Prakt/fritzsch/Sicherheit/mykeystore"+ " -storepass rplacd1"; System.out.println("-- invoke: "); System.out.println(" " + command); Runtime rt = Runtime.getRuntime(); Process p = rt.exec(command); String ss = "y\n"; p.getOutputStream().write(ss.getBytes()); p.getOutputStream().close(); p.waitFor(); System.out.println(" ... beendet mit RC="+ p.exitValue()); // Keystore-Datei lesen -----------------------------------KeyStore ks = KeyStore.getInstance("JKS","SUN"); char [] passwd1 = {'r','p','l','a','c','d','1'}; FileInputStream fi = new FileInputStream( "i:/Prakt/fritzsch/Sicherheit/mykeystore"); ks.load(fi,passwd1); // Message-Digest prüfen ----------------------------------MessageDigest md = MessageDigest.getInstance("MD5"); FileInputStream fius = new FileInputStream("belegis.dat"); byte [] org = {1,1,1,1,5,1,1,1,1,5,1,1,1,1,5,1,1,1,1,5, 1,1,1,1,5,1,1,1,1,5,1,1,1,1,5,1,1,1,1,5, 1,1,1,1,5,1,1,1,1,5,1,1,1,1,5,1,1,1,1,5, 1,1,1,1,5,1,1,1,1,5,1,1,1,1,5,1,1,1,1,5, 1,1,1,1,5,1,1,1,1,5,1,1,1,1,5,1,1,1,1,5,1}; int i = 0; org[i]=(byte)fius.read(); while (org[i]!=-1){ md.update(org[i]); i=i+1; org[i]=(byte)fius.read(); } fius.close(); FileInputStream fimd = new FileInputStream("belegis_MD5.dat"); byte [] dig = {1,1,1,1,5,1,1,1,1,5,1,1,1,1,5,1,0}; int j = 0; dig[j] = (byte)fimd.read(); while (j<15){ j=j+1; dig[j] = (byte)fimd.read(); } fimd.close(); byte [] medi =md.digest(); boolean vergleich=true; for (int k = 0; k<16; k++) if(dig[k]!=medi[k]) vergleich=false; System.out.println("-- Vergleich Message Digest:" + vergleich); // Sitzungsschlüssel deserialisieren -----------------------FileInputStream kfis = new FileInputStream( "i:/Prakt/fritzsch/Sicherheit/chiffkey.dat"); ObjectInputStream keyin = new ObjectInputStream(kfis); SecretKey desKey=(SecretKey)keyin.readObject(); System.out.println("-- Sitzungsschluessel deserialisiert"); // Datei chiffretext.dat dechiffrieren und ----------------// in belegis_zwi.dat ablegen FileInputStream fis = new FileInputStream("chiffretext.dat"); FileOutputStream fos = new FileOutputStream("belegis_zwi.dat"); CipherInputStream cis; Cipher desciph = Cipher.getInstance("DES/ECB/PKCS5Padding"); cis = new CipherInputStream(fis,desciph); desciph.init(Cipher.DECRYPT_MODE,desKey); byte [] ba = new byte [1]; int iii = cis.read(ba); while (iii != -1){ fos.write(ba,0,iii); iii = cis.read(ba); } fos.close(); fis.close(); System.out.println("-- Dechiffrierung erfolgreich"); // öffentlichen Schlüssel aus Certif. extrahieren ----------java.security.cert.X509Certificate cl = (java.security.cert.X509Certificate) ks.getCertificate(args[0]); PublicKey pub = cl.getPublicKey(); System.out.println("-- oeffentlicher Schluessel extrahiert"); // Gültigkeitsdauer des Zertifikates überprüfen -------------Date bef = cl.getNotBefore(); Date aft = cl.getNotAfter(); System.out.println("-- Zertifikat ist gueltig"); System.out.println(" vom: " + bef.toLocaleString()); System.out.println(" bis: " + aft.toLocaleString()); // Signatur-Objekt zum Prüfen initialisieren ----------------Signature dsa = Signature.getInstance("DSA"); dsa.initVerify(pub); // Zwischendatei belegis_zwi.dat lesen ----------------------File gesamtFile = new File("belegis_zwi.dat"); int sizef = (int)gesamtFile.length(); fis = new FileInputStream(gesamtFile); byte b = (byte)fis.read(); sizef--; byte c = (byte)fis.read(); sizef--; byte d = (byte)fis.read(); while ((d != -1)&&((b !='S')||(c != 'I')||(d !='G'))){ sizef--; dsa.update(b); b=c; c=d; d=(byte)fis.read(); } sizef--; // Signatur lesen -----------------------------------------System.out.println("Laenge der Signatur: "+sizef); byte [] sig = new byte[sizef]; int ii = 0; byte s = (byte)fis.read(); while (ii < sizef){ sig[ii] = s; ii++; s = (byte)fis.read(); } fis.close(); System.out.println("-- Signatur gelesen"); // Signatur pruefen ----------------------------------------boolean verifies = dsa.verify(sig); System.out.println("-- Signatur verifiziert:"+verifies); System.out.println("-- Ende"); } catch(Exception e){ System.out.println("error:"+e); } } } import import import import import java.applet.Applet; java.awt.*; java.awt.event.*; java.io.*; javax.swing.*; import List; public class HanoiVisual extends JApplet implements ActionListener{ JPanel jPanel0= new JPanel(); JPanel jPanel1= new JPanel(); JPanel jPanel2 = new JPanel(); JPanel jPanel3 = new JPanel(); JPanel jPanel4 = new JPanel(); JButton popbutton = new JButton("pop"); JButton pushbutton = new JButton("push"); JButton emptybutton = new JButton("emptyStack"); JButton runbutton = new JButton("run"); JButton stopbutton = new JButton("stop"); JPanel buttonPanel = new JPanel(); VisObject vo1 = new VisObject(0, jPanel1); VisObject vo2 = new VisObject(0, jPanel2); VisObject vo3 = new VisObject(0, jPanel3); public void init(){ try{ UIManager.setLookAndFeel( UIManager.getCrossPlatformLookAndFeelClassName()); Container contentPane= getContentPane(); contentPane.setBackground(Color.white); jPanel0.setBorder(BorderFactory.createEtchedBorder()); jPanel0.setLayout(new GridLayout(1,3,5,10));//3 Spalten jPanel1.setBorder(BorderFactory.createEtchedBorder()); jPanel1.setLayout(new GridLayout(10,1,5,0));//10 Zeilen for (int j=0;j<10;j++){ jPanel4= (JPanel)jPanel1.add(new MyJPanelInit(),j); } jPanel2.setBorder(BorderFactory.createEtchedBorder()); jPanel2.setLayout(new GridLayout(10,1,5,0));//10 Zeilen for (int j=0;j<10;j++){ jPanel4= (JPanel)jPanel2.add(new MyJPanelInit(),j); } jPanel3.setBorder(BorderFactory.createEtchedBorder()); jPanel3.setLayout(new GridLayout(10,1,5,0));//10 Zeilen for (int j=0;j<10;j++){ jPanel4= (JPanel)jPanel3.add(new MyJPanelInit(),j); } jPanel0.add(jPanel1); jPanel0.add(jPanel2); jPanel0.add(jPanel3); contentPane.add("Center",jPanel0); pushbutton.addActionListener(this); buttonPanel.add(pushbutton); popbutton.addActionListener(this); buttonPanel.add(popbutton); emptybutton.addActionListener(this); buttonPanel.add(emptybutton); runbutton.addActionListener(this); buttonPanel.add(runbutton); stopbutton.addActionListener(this); buttonPanel.add(stopbutton); contentPane.add("South",buttonPanel); validate(); }catch(Exception e){ } } public void actionPerformed(ActionEvent evt){ if(evt.getActionCommand().equals("pop")){ MyJPanel y = popvis(vo1); } if(evt.getActionCommand().equals("push")){ pushvis(vo1,new MyJPanel(vo1.i+1)); } if(evt.getActionCommand().equals("emptyStack")){ vo1.i=0; jPanel1.removeAll(); for (int j=0;j<10;j++){ jPanel4= (JPanel)jPanel1.add(new MyJPanelInit(),j); } vo2.i=0; jPanel2.removeAll(); for (int j=0;j<10;j++){ jPanel4= (JPanel)jPanel2.add(new MyJPanelInit(),j); } vo3.i=0; jPanel3.removeAll(); for (int j=0;j<10;j++){ jPanel4= (JPanel)jPanel3.add(new MyJPanelInit(),j); } paint(getGraphics()); } if(evt.getActionCommand().equals("run")){ hanoiinit(); validate(); } if(evt.getActionCommand().equals("stop")){ stop(); init(); } } public void pushvis(VisObject p,MyJPanel x){ p.i++; p.jP.remove(10-p.i); jPanel4= (JPanel)p.jP.add(x,10-p.i); validate(); paint(getGraphics()); } public MyJPanel popvis(VisObject p){ MyJPanel x = (MyJPanel)p.jP.getComponent(10-p.i); p.jP.remove(10-p.i); jPanel4= (JPanel)p.jP.add(new MyJPanelInit(),10-p.i); validate(); paint(getGraphics()); p.i--; return x; } public void hanoiinit(){ List a = new List(); a = a.cons(vo1); for (int j=0;j<vo1.i;j++) a= a.cons(new Integer(vo1.i-j)); a=a.reverse(); a.princ(); List b = new List(); b = b.cons(vo2); b.princ(); List c = new List(); c = c.cons(vo3); c.princ(); hanoi(a,b,c); } public void hanoi(List a, List b, List c){ if (a.cdr().cdr().nullp()) move(a, b); else { hanoi(a.cdr().cdr().cons(a.car()),c,b); validate(); move(a, b); validate(); hanoi(c.append(a.cdr().cdr()),b,(new List()).cons(a.car())); validate(); } } public void move(List a, List b){ MyJPanel x = popvis((VisObject)a.car()); validate(); pushvis((VisObject)b.car(),x); validate(); try{ Thread.currentThread().sleep(1200); validate(); } catch(InterruptedException e){ } } public void paint(Graphics g){ getContentPane().paintAll(g); } } class MyJPanel extends JPanel{ public MyJPanel(int i){ super(); this.setBackground(Color.black); this.add(new Scheibe(i)); } } // cyan class Scheibe extends JPanel{ public Scheibe(int i){ super(); int x = this.getWidth(); this.setBorder(BorderFactory.createEmptyBorder( 0,x+93-10*i,0,x+93-10*i)); this.setBackground(Color.yellow); this.add(new JLabel(String.valueOf(i))); } } class MyJPanelInit extends JPanel{ public MyJPanelInit(){ super(); this.setBackground(Color.black); } } class VisObject { public int i; public JPanel jP; public VisObject(int n, JPanel p){ i=n; jP=p; } }