30 April 1999
Date: Thu, 29 Apr 1999 13:48:28 -0700 From: "J. Orlin Grabbe" <kalliste@aci.net> To: "cryptography@c2.net" <cryptography@c2.net> Subject: Triple-DES with the Cryptix class library I have found the Cryptix class library works fine for 3DES and other encryptions. It's a little slow. Here are two java programs I wrote which illustrate how 3DES works using the Cryptix class library. The first program encrypts a string (in the program) using a key (in the program), and prints the string, the key, and the encrypted string out to a text file ("DES-EDE3.out"). Sample output is shown following the program listing. The second program generates its own 3DES key, prints this out to a textfile ("DES-EDE3.out"), reads in a plaintext file (passed as an argument to main()), encrypts the plaintext file with the key, and writes the ciphertext to a ciphertext file. Then, to check the process, it deciphers the ciphertext bytes that are still in memory and writes these out to to the textfile. Next, it reads in the ciphertext file, decrypts the ciphertext, and also writes the decrypted bytes to the textfile. Sample output is shown also. Orlin Grabbe http://www.aci.net/kalliste/homepage.html /*********************test2x3DES.java***************/ /********************************************/ /* test2x3DES.java takes a 3DES key input */ /* and a text string from the program, */ /* encrypts the string, and writes the key */ /* the plaintext string, and the encrypted */ /* result to a file DES-3EDE3.out */ /* If cipher block chaining (CBC) is used */ /* instead of ECB, an intilization vector */ /* must be set first (lines not included). */ /* --Orlin Grabbe */ /********************************************/ import java.io.*; import java.security.*; import java.math.*; import cryptix.util.core.BI; import cryptix.util.core.ArrayUtil; import cryptix.util.core.Hex; import cryptix.provider.key.*; class test2x3DES { public static void main (String[] args) { try { FileOutputStream outFile1 = new FileOutputStream("DES- EDE3.out"); // Note: PrintStream is deprecated, but still works fine in jdk1.1.7b PrintStream output1 = new PrintStream(outFile1); RawSecretKey key2 = new RawSecretKey("DES- EDE3",Hex.fromString("3812A419C63BE771AD9F61FEFA20CE633812A419C63 BE771")); //Use the following line instead for DES encryption //RawSecretKey key2 = new RawSecretKey("DES",Hex.fromString("3812A419C63BE771")); RawKey rkey = (RawKey) key2; byte[] yval = rkey.getEncoded(); BigInteger Bkey = new BigInteger(yval); String w = cryptix.util.core.BI.dumpString(Bkey); output1.println("The Encryption Key = " + w); Cipher des=Cipher.getInstance("DES- EDE3/ECB/NONE","Cryptix"); //Use the following line instead for DES encryption //Cipher des=Cipher.getInstance("DES/ECB/NONE","Cryptix"); des.initEncrypt(key2); byte[] ciphertext = des.crypt(Hex.fromString("01010101010101010102030405060708090A0B0 C0D0E0F101112131415161718")); /* print out length and representation of ciphertext */ output1.print("\n"); output1.println("ciphertext.length = " + ciphertext.length); BigInteger Bciph = new BigInteger(ciphertext); w = cryptix.util.core.BI.dumpString(Bciph); output1.println("Ciphertext for simple encryption = " + w); /* decrypt ciphertext */ des.initDecrypt(key2); ciphertext = des.crypt(ciphertext); output1.print("\n"); output1.println("plaintext.length = " + ciphertext.length); /* print out representation of decrypted ciphertext */ Bciph = new BigInteger(ciphertext); w = cryptix.util.core.BI.dumpString(Bciph); output1.println("Plaintext for simple encryption = " + w); output1.println(" "); output1.close(); } catch (Exception e) { System.err.println("Caught exception " + e.toString()); } }} /********************end of test2x3DES.java******************/ /******************sample output from test2xDES.java**********/ The Encryption Key = Multi-Precision Integer 190 bits long... sign: Positive magnitude: 3812A419C63BE771 AD9F61FEFA20CE63 3812A419C63BE771 ciphertext.length = 32 Ciphertext for simple encryption = Multi-Precision Integer 255 bits long... sign: Positive magnitude: 741038365B8C4BC2 01B45F3A1C9C703E 5DE9007B2288BDBD 5203FEB4F80C5BD0 plaintext.length = 32 Plaintext for simple encryption = Multi-Precision Integer 249 bits long... sign: Positive magnitude: 0101010101010101 0102030405060708 090A0B0C0D0E0F10 1112131415161718 /***************end of sample output test2x3DES.java*************/ /**********************testx3DES.java************************/ /********************************************/ /* testx3DES generates its own 3DES key */ /* then reads in a plaintext file, encrypts */ /* the plaintext file, writes the encrypted */ /* bytes out to a ciphertext file. Next it */ /* decrypts the ciphertext bytes which are */ /* still in memory, and writes these to the */ /* general output file. Next it reads in */ /* the ciphertext file, decrypts it and */ /* writes this to the general output file. */ /* If CBC is used instead of ECB, lines to */ /* set an initialized vector will have to */ /* be set. */ /* --Orlin Grabbe */ /*------------------------------------------*/ import java.io.*; import java.security.*; import java.math.*; import cryptix.util.core.BI; import cryptix.util.core.ArrayUtil; import cryptix.util.core.Hex; import cryptix.provider.key.*; class testx3DES { public static void main (String[] args) { try { FileOutputStream outFile1 = new FileOutputStream("DES- EDE3.out"); FileOutputStream outFile2 = new FileOutputStream("DES3CIPH.out"); //PrintStream is deprecated, but works fine in jdk1.1.7b PrintStream output1 = new PrintStream(outFile1); PrintStream output2 = new PrintStream(outFile2); /* generate key for file encryption */ SecureRandom random = new SecureRandom(); KeyGenerator keygen = KeyGenerator.getInstance("DES-EDE3"); keygen.initialize(random); Key key = keygen.generateKey(); RawKey rkey = (RawKey) key; byte[] yval = rkey.getEncoded(); BigInteger Bkey = new BigInteger(yval); String w = cryptix.util.core.BI.dumpString(Bkey); output1.println("The Encryption Key = " + w); /* Define and Initialize Key */ Cipher des=Cipher.getInstance("DES- EDE3/ECB/PKCS#5","Cryptix"); des.initEncrypt(key); /* read in the input file */ FileInputStream fis = new FileInputStream(args[0]); byte b; int bi; char bc; byte bb[] = new byte[1024]; int count=0; output1.println("This is a copy of the input file: "); output1.println(" "); while (fis.available() != 0) { b = (byte) fis.read(); bi = (int) b; bc = (char) b; output1.print(bc); bb[count] = b; count++; }; output1.print("\n"); output1.print("\n"); output1.println("The number of bytes in the plaintext input file is = " + count); fis.close(); /* do the encryption */ int remain = count%8; int pcount = count + remain; byte[] bt = new byte[pcount]; int i; for(i=0;i<pcount;i++) bt[i] = bb[i]; byte[] ciphertext = des.crypt(bt); output1.print("\n"); output1.println("ciphertext.length = " + ciphertext.length); /* print out representation of ciphertext to general output file */ BigInteger Bciph = new BigInteger(ciphertext); w = cryptix.util.core.BI.dumpString(Bciph); output1.println("Ciphertext = " + w); /* print ciphertext to ciphertext specific file */ output2.write(ciphertext,0,ciphertext.length); output2.close(); /* decrypt ciphertext from memeory */ des.initDecrypt(key); byte[] decrypted = des.crypt(ciphertext); BigInteger Bplain = new BigInteger(decrypted); w = cryptix.util.core.BI.dumpString(Bplain); output1.println("Plaintext (decrypted from memory) = " + w); /* write the decrypted bytes to general outputfile */ char c; output1.println("Following is a copy of the decrypted (from memory) bytes: "); output1.print("\n"); for(i=0;i<count;i++) { c = (char) decrypted[i]; output1.print(c); } output1.println(" "); /* read in ciphertext from file */ fis = new FileInputStream("DES3CIPH.out"); bb = new byte[1024]; pcount=0; while (fis.available() != 0) { b = (byte) fis.read(); bb[pcount] = b; pcount++; }; output1.print("\n"); output1.println("The number of bytes in the ciphertext input file is " + pcount); fis.close(); des.initDecrypt(key); bt = new byte[pcount]; for(i=0;i<pcount;i++) bt[i] = bb[i]; decrypted = des.crypt(bt); Bplain = new BigInteger(decrypted); w = cryptix.util.core.BI.dumpString(Bplain); output1.println("Plaintext (decrypted from cipher file) = " + w); /* write the decrypted bytes to the general output file */ output1.println("Following is a copy of the decrypted (from cipher file) bytes: "); output1.print("\n"); for(i=0;i<count;i++) { c = (char) decrypted[i]; output1.print(c); } output1.println(" "); output1.close(); } catch (Exception e) { System.err.println("Caught exception " + e.toString()); } }} /***********************end of testx3DES.java**********/ /****************sample output from testx3DES.java**********/ The Encryption Key = Multi-Precision Integer 190 bits long... sign: Negative magnitude: C61722CA3F7DEEA6 7E4D87A928908B47 594282C07D1D5F69 This is a copy of the input file: Senator Hand N. Till Washington, DC Dear Senator: This letter is to inform you we have opened account no. 338907021 on your behalf, and deposted therein a legislative incentive payment of $1 million. For withdrawl, you will need to use your password BJRGUD7693. Yours very truly, Arnold C. Creole Vice President Greater Caribbean Bank The number of bytes in the plaintext input file is = 355 ciphertext.length = 360 Ciphertext = Multi-Precision Integer 2879 bits long... sign: Negative magnitude: Hexadecimal dump of 360 bytes... 0: 8E08C06612267EEB 4FF9AF49EDB6743D BE3BBE82EAE64261 A40BD6A6D814B230 32: 16651BD3E90B829D 910ED9751DF82007 916C2BD72A5D53AA CB876CC7C7CA0DFF 64: 419B3948123A8715 7A801E129185BAA3 E159FABCFE8E98EE 89299B3964B438F6 96: 15012D94B21F3F55 013B9B6A9B1A3474 1017229617E8D47C 9618FB74804E80D2 128: 1ECD059819B7729E FBF47E01EF4B6E67 69C99F1E212905B0 63B2F3D4725CC842 160: C84C4B55D59029D8 5551EBE5AC5A1D2C 7D09CCDEADFD214E 49B0979B07FACD4D 192: 3B626E3B718F5D46 C3D8C6B8E7279391 AFF48BE961FBA899 9ADEC794F21DE1E7 224: 4B76EFBE2E6FE416 19CFDD42D482B03D C32A459AB10E1417 C3CE45CC148BBB48 256: 315CFCBD4E45320E 750C5B1B9A6D89D9 AE5026266BDEA3D0 FD71F2D7C507879D 288: 0E0EB7B19FEDA173 06D27737673BF003 68B2DAF4747BFEF8 9C3F947E1D19C9B7 320: AD2CF4A1275C2E38 EFAAE0B2BB076ACD 7DCE861B374B63D2 E12DD856A0262A49 352: 29B2B1C281C009CF Plaintext (decrypted from memory) = Multi-Precision Integer 2863 bits long... sign: Positive magnitude: Hexadecimal dump of 358 bytes... 0: 53656E61746F7220 48616E64204E2E20 54696C6C0D0A5761 7368696E67746F6E 32: 2C2044430D0A0D0A 446561722053656E 61746F723A0D0A0D 0A54686973206C65 64: 7474657220697320 746F20696E666F72 6D20796F75207765 20686176650D0A6F 96: 70656E6564206163 636F756E74206E6F 2E20333338393037 303231206F6E2079 128: 6F75720D0A626568 616C662C20616E64 206465706F737465 6420746865726569 160: 6E20610D0A6C6567 69736C6174697665 20696E63656E7469 7665207061796D65 192: 6E74206F660D0A24 31206D696C6C696F 6E2E2020466F7220 7769746864726177 224: 6C2C20796F752077 696C6C0D0A6E6565 6420746F20757365 20796F7572207061 256: 7373776F72642042 4A52475544373639 332E0D0A0D0A596F 7572732076657279 288: 207472756C792C0D 0A0D0A41726E6F6C 6420432E20437265 6F6C650D0A566963 320: 6520507265736964 656E740D0A477265 6174657220436172 69626265616E2042 352: 616E6B000000 Following is a copy of the decrypted (from memory) bytes: Senator Hand N. Till Washington, DC Dear Senator: This letter is to inform you we have opened account no. 338907021 on your behalf, and deposted therein a legislative incentive payment of $1 million. For withdrawl, you will need to use your password BJRGUD7693. Yours very truly, Arnold C. Creole Vice President Greater Caribbean Bank The number of bytes in the ciphertext input file is 360 Plaintext (decrypted from cipher file) = Multi-Precision Integer 2863 bits long... sign: Positive magnitude: Hexadecimal dump of 358 bytes... 0: 53656E61746F7220 48616E64204E2E20 54696C6C0D0A5761 7368696E67746F6E 32: 2C2044430D0A0D0A 446561722053656E 61746F723A0D0A0D 0A54686973206C65 64: 7474657220697320 746F20696E666F72 6D20796F75207765 20686176650D0A6F 96: 70656E6564206163 636F756E74206E6F 2E20333338393037 303231206F6E2079 128: 6F75720D0A626568 616C662C20616E64 206465706F737465 6420746865726569 160: 6E20610D0A6C6567 69736C6174697665 20696E63656E7469 7665207061796D65 192: 6E74206F660D0A24 31206D696C6C696F 6E2E2020466F7220 7769746864726177 224: 6C2C20796F752077 696C6C0D0A6E6565 6420746F20757365 20796F7572207061 256: 7373776F72642042 4A52475544373639 332E0D0A0D0A596F 7572732076657279 288: 207472756C792C0D 0A0D0A41726E6F6C 6420432E20437265 6F6C650D0A566963 320: 6520507265736964 656E740D0A477265 6174657220436172 69626265616E2042 352: 616E6B000000 Following is a copy of the decrypted (from cipher file) bytes: Senator Hand N. Till Washington, DC Dear Senator: This letter is to inform you we have opened account no. 338907021 on your behalf, and deposted therein a legislative incentive payment of $1 million. For withdrawl, you will need to use your password BJRGUD7693. Yours very truly, Arnold C. Creole Vice President Greater Caribbean Bank /**********end of sample output from test2x3DES.java**********/