Advertisement
Guest User

Untitled

a guest
Sep 13th, 2013
274
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 5.49 KB | None | 0 0
  1. import java.io.FilterOutputStream;
  2. import java.io.IOException;
  3. import java.io.OutputStream;
  4.  
  5. import javax.crypto.BadPaddingException;
  6. import javax.crypto.Cipher;
  7. import javax.crypto.IllegalBlockSizeException;
  8. import javax.crypto.Mac;
  9.  
  10. /**
  11.  * Based on OpenJDK7 CipherOutputStream
  12.  * Original here: http://pastebin.com/73uhvB0b
  13.  */
  14. public class CipherHmacOutputStream extends FilterOutputStream {
  15.     // the cipher engine to use to process stream data
  16.     private Cipher cipher;
  17.  
  18.     // the underlying output stream
  19.     private OutputStream output;
  20.  
  21.     /* the buffer holding one byte of incoming data */
  22.     private byte[] ibuffer = new byte[1];
  23.  
  24.     // the buffer holding data ready to be written out
  25.     private byte[] obuffer;
  26.    
  27.     private Mac mac;
  28.     private byte[] iv;
  29.  
  30.     /**
  31.      *
  32.      * Constructs a CipherOutputStream from an OutputStream and a
  33.      * Cipher.
  34.      * <br>Note: if the specified output stream or cipher is
  35.      * null, a NullPointerException may be thrown later when
  36.      * they are used.
  37.      *
  38.      * @param os  the OutputStream object
  39.      * @param c   an initialized Cipher object
  40.      */
  41.     public CipherHmacOutputStream(OutputStream os, Cipher c, Mac m, byte[] iv) {
  42.         super(os);
  43.         output = os;
  44.         cipher = c;
  45.         mac = m;
  46.         this.iv = iv;
  47.     };
  48.    
  49.     /**
  50.      * Writes the specified byte to this output stream.
  51.      *
  52.      * @param      b   the <code>byte</code>.
  53.      * @exception  IOException  if an I/O error occurs.
  54.      * @since      JCE1.2
  55.      */
  56.     public void write(int b) throws IOException {
  57.         ibuffer[0] = (byte) b;
  58.         obuffer = cipher.update(ibuffer, 0, 1);
  59.         if (obuffer != null) {
  60.             mac.update(obuffer);
  61.             output.write(obuffer);
  62.             obuffer = null;
  63.         }
  64.     };
  65.  
  66.     /**
  67.      * Writes <code>b.length</code> bytes from the specified byte array
  68.      * to this output stream.
  69.      * <p>
  70.      * The <code>write</code> method of
  71.      * <code>CipherOutputStream</code> calls the <code>write</code>
  72.      * method of three arguments with the three arguments
  73.      * <code>b</code>, <code>0</code>, and <code>b.length</code>.
  74.      *
  75.      * @param      b   the data.
  76.      * @exception  NullPointerException if <code>b</code> is null.
  77.      * @exception  IOException  if an I/O error occurs.
  78.      * @see        javax.crypto.CipherOutputStream#write(byte[], int, int)
  79.      * @since JCE1.2
  80.      */
  81.     public void write(byte b[]) throws IOException {
  82.         write(b, 0, b.length);
  83.     }
  84.  
  85.     /**
  86.      * Writes <code>len</code> bytes from the specified byte array
  87.      * starting at offset <code>off</code> to this output stream.
  88.      *
  89.      * @param      b     the data.
  90.      * @param      off   the start offset in the data.
  91.      * @param      len   the number of bytes to write.
  92.      * @exception  IOException  if an I/O error occurs.
  93.      * @since      JCE1.2
  94.      */
  95.     public void write(byte b[], int off, int len) throws IOException {
  96.         obuffer = cipher.update(b, off, len);
  97.         if (obuffer != null) {
  98.             mac.update(obuffer);
  99.             output.write(obuffer);
  100.             obuffer = null;
  101.         }
  102.     }
  103.  
  104.     /**
  105.      * Flushes this output stream by forcing any buffered output bytes
  106.      * that have already been processed by the encapsulated cipher object
  107.      * to be written out.
  108.      *
  109.      * <p>Any bytes buffered by the encapsulated cipher
  110.      * and waiting to be processed by it will not be written out. For example,
  111.      * if the encapsulated cipher is a block cipher, and the total number of
  112.      * bytes written using one of the <code>write</code> methods is less than
  113.      * the cipher's block size, no bytes will be written out.
  114.      *
  115.      * @exception  IOException  if an I/O error occurs.
  116.      * @since      JCE1.2
  117.      */
  118.     public void flush() throws IOException {
  119.         if (obuffer != null) {
  120.             mac.update(obuffer);
  121.             output.write(obuffer);
  122.             obuffer = null;
  123.         }
  124.         output.flush();
  125.     }
  126.  
  127.     /**
  128.      * Closes this output stream and releases any system resources
  129.      * associated with this stream.
  130.      * <p>
  131.      * This method invokes the <code>doFinal</code> method of the encapsulated
  132.      * cipher object, which causes any bytes buffered by the encapsulated
  133.      * cipher to be processed. The result is written out by calling the
  134.      * <code>flush</code> method of this output stream.
  135.      * <p>
  136.      * This method resets the encapsulated cipher object to its initial state
  137.      * and calls the <code>close</code> method of the underlying output
  138.      * stream.
  139.      *
  140.      * @exception  IOException  if an I/O error occurs.
  141.      * @since      JCE1.2
  142.      */
  143.     public void close() throws IOException {
  144.         try {
  145.             obuffer = cipher.doFinal();
  146.         } catch (IllegalBlockSizeException e) {
  147.             obuffer = null;
  148.         } catch (BadPaddingException e) {
  149.             obuffer = null;
  150.         }
  151.         try {
  152.             flush();
  153.         } catch (IOException ignored) {}
  154.        
  155.         writeHmac();
  156.        
  157.         out.close();
  158.     }  
  159.    
  160.     private void writeHmac() throws IOException {
  161.         try {
  162.             // Include IV & algorithm details in HMAC
  163.             mac.update(iv);
  164.             mac.update(cipher.getAlgorithm().getBytes("UTF8"));
  165.             mac.update(cipher.getParameters().getEncoded());
  166.            
  167.             // Write HMAC
  168.             byte[] macBytes = mac.doFinal();
  169.             out.write(macBytes);
  170.         }
  171.         catch (Exception e) {
  172.             throw new IOException(e);
  173.         }      
  174.     }
  175. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement