// Java salauksenkäyttöesimerkki SJ import javax.crypto.*; import javax.crypto.spec.*; import java.io.*; import java.lang.*; import java.util.*; import java.security.*; import java.io.Console; public class SalausApu { // oletusarvot static String salain = "Blowfish"; // AES, DES, Blowfish static int avainPituus = 128; // AES, Blowfish: 128, DES: 64 // salaa objektin kysymällä avain käyttäjältä public static SealedObject salaaOlio(Serializable o, SecretKeySpec avain) { try { // alustaan salain Cipher c = Cipher.getInstance(salain); c.init(Cipher.ENCRYPT_MODE, avain); // salataan koko olio SealedObject so = new SealedObject(o, c); return so; } catch (Exception e) { System.err.println("SealedObject-esimerkki epäonnistui: " + e); } return null; } public static Object puraOlio(SealedObject so, SecretKeySpec avain) { try { // alustaan salain Cipher c = Cipher.getInstance(salain); c.init(Cipher.DECRYPT_MODE, avain); Object o = so.getObject(c); return o; } catch (Exception e) { System.err.println("SealedObject-esimerkki epäonnistui: " + e); } return null; } // lukee tiedostosta public static SecretKeySpec lueAvain(String tiedosto) { SecretKeySpec kp = null; try { byte [] binAvain = TiedostoEsimerkki.LueTiedosto(tiedosto); if (binAvain == null || binAvain.length != avainPituus/8) return lueAvain(); // sitten käyttäjältä // tehdään itse avain salausalgoritmille kp = new SecretKeySpec(binAvain, salain); System.out.println("Avain = |" + bintohex(kp.getEncoded()) + "|"); } catch (Exception e) { System.err.println("Avaimenluonti epäonnistui " + e); } return kp; } // lueAvain(tiedosto) public static SecretKeySpec lueAvain() { return lueAvain(avainPituus); } // lukee avaimen käyttäjältä, palauttaa SecretKeySpec public static SecretKeySpec lueAvain(int pituus) { SecretKeySpec kp = null; String rivi; byte [] bin = null; Console c = System.console(); try { String kehote = "Anna avain tai avainlause (" + pituus/4 + " heksanumeroa tai pitkä ascii merkkijono) \n : "; if (c == null) { // System.console ei käytettävissä BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); System.out.print(kehote); rivi = in.readLine(); } else { // salasana näyttämättä sitä char[] mt = c.readPassword(kehote); rivi = new String(mt); } // tarkastetaan onko avain pelkkää heksaa vai ei boolean onkoheksa = true; for (int i = 0; i < rivi.length(); i++) if (Character.digit(rivi.charAt(i), 16) < 0) { onkoheksa = false; break; } // tarkastetaan heksa-avaimen pituus if (onkoheksa && rivi.length() != pituus/4) { System.err.println("Väärä heksa-avainpituus (" + rivi.length() + "/" + pituus/4 + ")"); onkoheksa = false; } // muutetaan binäärimuotoon if (onkoheksa) bin = hextobin(rivi); else bin = asciitobin(rivi); // tehdään itse avain salausalgoritmille kp = new SecretKeySpec(bin, 0, pituus/8, salain); System.out.println("Avain = |" + bintohex(kp.getEncoded()) + "|"); } catch (Exception e) { System.err.println("Avaimenluonti epäonnistui " + e); } return kp; } // lueAvain() // heksamerkkijonosta binääritaulukko public static byte[] hextobin(String s) { int pituus = (s.length()+1)/2; byte[] A = new byte[pituus]; for (int i = 0; i < pituus; i++) A[i] = Integer.valueOf(s.substring(i*2, i*2+2), 16).byteValue(); return A; } // palauttaa merkkijonon MD5 tiivisteen (128-bittiä) tavutaulukossa public static byte[] asciitobin(String s) { byte[] A = null; try { MessageDigest md = MessageDigest.getInstance("MD5"); A = md.digest(s.getBytes()); } catch (Exception e) { System.err.println("Tiiviste epäonnistui " + e); } return A; } // palauttaa tavutaulukon heksaesityksen merkkijonona public static String bintohex(byte[] A) { int pituus = A.length; StringBuffer sb = new StringBuffer(pituus*2); for (int i = 0; i < pituus; i++) { if ((A[i] & 0xFF) < 0x10) sb.append("0"); sb.append(Integer.toHexString(A[i] & 0xFF)); } return sb.toString(); } } // class