1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership. 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License. You may obtain a copy of the License at 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage javax.crypto; 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.FilterOutputStream; 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException; 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.OutputStream; 23ff8234c90ecab9f1db368924bf92a5b16460f9b5Elliott Hughesimport libcore.io.Streams; 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This class wraps an output stream and a cipher so that {@code write} methods 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * send the data through the cipher before writing them to the underlying output 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * stream. 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The cipher must be initialized for the requested operation before being used 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * by a {@code CipherOutputStream}. For example, if a cipher initialized for 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * encryption is used with a {@code CipherOutputStream}, the {@code 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * CipherOutputStream} tries to encrypt the data writing it out. 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class CipherOutputStream extends FilterOutputStream { 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final Cipher cipher; 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Creates a new {@code CipherOutputStream} instance for an {@code 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * OutputStream} and a {@code Cipher}. 42ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson * 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param os 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the output stream to write data to. 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param c 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the cipher to process the data with. 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public CipherOutputStream(OutputStream os, Cipher c) { 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(os); 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project cipher = c; 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Creates a new {@code CipherOutputStream} instance for an {@code 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * OutputStream} without a cipher. 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * A {@code NullCipher} is created to process the data. 58ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson * 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param os 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the output stream to write the data to. 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected CipherOutputStream(OutputStream os) { 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this(os, new NullCipher()); 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Writes the single byte to this cipher output stream. 68ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson * 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param b 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the byte to write. 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an error occurs. 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 74ff8234c90ecab9f1db368924bf92a5b16460f9b5Elliott Hughes @Override public void write(int b) throws IOException { 75ff8234c90ecab9f1db368924bf92a5b16460f9b5Elliott Hughes Streams.writeSingleByte(this, b); 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Writes the {@code len} bytes from buffer {@code b} starting at offset 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@code off} to this cipher output stream. 81ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson * 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param b 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the buffer. 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param off 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the offset to start at. 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param len 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the number of bytes. 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an error occurs. 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 91ff8234c90ecab9f1db368924bf92a5b16460f9b5Elliott Hughes @Override public void write(byte[] b, int off, int len) throws IOException { 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (len == 0) { 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] result = cipher.update(b, off, len); 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (result != null) { 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project out.write(result); 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Flushes this cipher output stream. 103ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson * 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an error occurs 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void flush() throws IOException { 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project out.flush(); 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Close this cipher output stream. 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * On the underlying cipher {@code doFinal} will be invoked, and any 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * buffered bytes from the cipher are also written out, and the cipher is 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * reset to its initial state. The underlying output stream is also closed. 118ce9ec01c0b6da3f3ba01e9c81cc3e5a461aabfb6Jesse Wilson * 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an error occurs. 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void close() throws IOException { 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] result; 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (cipher != null) { 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project result = cipher.doFinal(); 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (result != null) { 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project out.write(result); 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (out != null) { 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project out.flush(); 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (BadPaddingException e) { 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IOException(e.getMessage()); 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IllegalBlockSizeException e) { 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IOException(e.getMessage()); 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } finally { 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (out != null) { 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project out.close(); 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 146