JAVA   78

Karn

Guest on 14th August 2022 06:44:28 AM

  1. import java.io.*;
  2. import java.util.Date;
  3. import java.math.BigInteger;
  4. import java.security.*;
  5.  
  6. class Karn {
  7.    final int RADIX=32;
  8.    final int PADSIZE=40; // Plaintext buffer */
  9.    
  10.    private byte key[];
  11.    private byte key_left[];
  12.    private byte key_right[];
  13.  
  14.    static SecureRandom sr = null;  // This is expensive.  We only need one
  15.    static MessageDigest md = null; // This will be shared.
  16.  
  17.    Karn (BigInteger bi) {
  18.       if (sr == null) sr = new SecureRandom();
  19.       key = bi.toByteArray();
  20.  
  21.       // Digest encryption needs keys split into two halves
  22.       key_left =  new byte[key.length/2];
  23.       key_right = new byte[key.length/2];
  24.  
  25.       for (int i = 0 ; i < key.length/2 ; i++) {
  26.          key_left[i] = key[i];
  27.          key_right[i] = key[i+key.length/2];
  28.       }
  29.  
  30.       try {
  31.          md = MessageDigest.getInstance("SHA");
  32.       } catch (NoSuchAlgorithmException e) {
  33.          System.err.println("Yow! NoSuchAlgorithmException. Abandon all hope");
  34.       }
  35.    }
  36.    
  37.    // Encrypt the string using the karn algorithm
  38.    String encrypt(String plaintext) {
  39.       byte[] plain_left, plain_right;
  40.       byte[] ciph_left, ciph_right;
  41.       byte[] digest;
  42.      
  43.       // These buffers are used for the encryption.
  44.       byte input[] = StringToBytes(plaintext); // Pad the string
  45.        
  46.       plain_left =  new byte[PADSIZE/2];
  47.       plain_right = new byte[PADSIZE/2];
  48.  
  49.       ciph_left =  new byte[PADSIZE/2];
  50.       ciph_right =  new byte[PADSIZE/2];
  51.  
  52.       digest = new byte[PADSIZE/2];  // Temp storage for the hash
  53.  
  54.       // Our pointer into the workspace
  55.       int cursor = 0;
  56.  
  57.       // Guard Byte for the ciphertext
  58.       out.write(42);
  59.  
  60.       while (cursor < input.length) {
  61.          // Copy the next slab into the left and right
  62.          for (int i=0 ; i < PADSIZE/2 ; i++) {
  63.             plain_left[i] = input[cursor + i];
  64.             plain_right[i] = input[cursor + PADSIZE/2 + i];        
  65.          }
  66.          
  67.          // Hash the left plaintext with the left key
  68.          md.reset(); // Start the hash fresh
  69.          md.update(plain_left);
  70.          md.update(key_left);
  71.          digest = md.digest(); // Get out the digest bits
  72.          // XOR the digest with the right plaintext for the right c-text
  73.          // Right half
  74.          for (int i=0 ; i < PADSIZE/2 ; i++)
  75.             ciph_right[i] = (byte)(digest[i] ^ plain_right[i]);
  76.          
  77.          // Now things get a little strange
  78.          md.reset();
  79.          md.update(ciph_right);
  80.          md.update(key_right);
  81.          digest = md.digest();
  82.          for (int i=0 ; i < PADSIZE/2 ; i++)
  83.             ciph_left[i] = (byte) (digest[i] ^ plain_left[i]);
  84.          
  85.          out.write(ciph_left,0,PADSIZE/2);
  86.          out.write(ciph_right,0,PADSIZE/2);
  87.          cursor += PADSIZE;
  88.       }
  89.       BigInteger bi_out = new BigInteger(out.toByteArray());
  90.       return(bi_out.toString(RADIX));
  91.    }
  92.  
  93.    // Decrypt the ciphertext by running Karn in reverse
  94.    String decrypt(String ciphertext) {
  95.       BigInteger bi;
  96.       byte input[];
  97.       byte[] plain_left,plain_right;
  98.       byte[] ciph_left,ciph_right;
  99.       byte[] digest;
  100.      
  101.       // Convert to a BigInteger, extract the bytes
  102.       bi = new BigInteger(ciphertext,RADIX);
  103.       ...
  104.       ...
  105.       return StripPadding(out.toByteArray());
  106.    }
  107.  
  108.    // Padding
  109.    private byte[] StringToBytes(String input) {
  110.       byte scratch[];
  111.  
  112.       scratch = input.getBytes();
  113.       int len = input.length();
  114.       ...
  115.       return (buffer.toByteArray());
  116.    }
  117.  
  118.    // Strip the header off the byte array and return the string
  119.    private String StripPadding (byte input[]) {
  120.       int i = 0;
  121.       ...
  122.       return (new String(buffer.toByteArray()));
  123.    }
  124. }

Raw Paste


Login or Register to edit or fork this paste. It's free.