comparison src/com/trilead/ssh2/crypto/cipher/CipherOutputStream.java @ 0:0ce5cc452d02

initial version
author Carl Byington <carl@five-ten-sg.com>
date Thu, 22 May 2014 10:41:19 -0700
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:0ce5cc452d02
1
2 package com.trilead.ssh2.crypto.cipher;
3
4 import java.io.IOException;
5 import java.io.OutputStream;
6
7 /**
8 * CipherOutputStream.
9 *
10 * @author Christian Plattner, plattner@trilead.com
11 * @version $Id: CipherOutputStream.java,v 1.1 2007/10/15 12:49:55 cplattne Exp $
12 */
13 public class CipherOutputStream {
14 BlockCipher currentCipher;
15 OutputStream bo;
16 byte[] buffer;
17 byte[] enc;
18 int blockSize;
19 int pos;
20
21 /*
22 * We cannot use java.io.BufferedOutputStream, since that is not available
23 * in J2ME. Everything could be improved here alot.
24 */
25
26 final int BUFF_SIZE = 2048;
27 byte[] out_buffer = new byte[BUFF_SIZE];
28 int out_buffer_pos = 0;
29
30 public CipherOutputStream(BlockCipher tc, OutputStream bo) {
31 this.bo = bo;
32 changeCipher(tc);
33 }
34
35 private void internal_write(byte[] src, int off, int len) throws IOException {
36 while (len > 0) {
37 int space = BUFF_SIZE - out_buffer_pos;
38 int copy = (len > space) ? space : len;
39 System.arraycopy(src, off, out_buffer, out_buffer_pos, copy);
40 off += copy;
41 out_buffer_pos += copy;
42 len -= copy;
43
44 if (out_buffer_pos >= BUFF_SIZE) {
45 bo.write(out_buffer, 0, BUFF_SIZE);
46 out_buffer_pos = 0;
47 }
48 }
49 }
50
51 private void internal_write(int b) throws IOException {
52 out_buffer[out_buffer_pos++] = (byte) b;
53
54 if (out_buffer_pos >= BUFF_SIZE) {
55 bo.write(out_buffer, 0, BUFF_SIZE);
56 out_buffer_pos = 0;
57 }
58 }
59
60 public void flush() throws IOException {
61 if (pos != 0)
62 throw new IOException("FATAL: cannot flush since crypto buffer is not aligned.");
63
64 if (out_buffer_pos > 0) {
65 bo.write(out_buffer, 0, out_buffer_pos);
66 out_buffer_pos = 0;
67 }
68
69 bo.flush();
70 }
71
72 public void changeCipher(BlockCipher bc) {
73 this.currentCipher = bc;
74 blockSize = bc.getBlockSize();
75 buffer = new byte[blockSize];
76 enc = new byte[blockSize];
77 pos = 0;
78 }
79
80 private void writeBlock() throws IOException {
81 try {
82 currentCipher.transformBlock(buffer, 0, enc, 0);
83 }
84 catch (Exception e) {
85 throw(IOException) new IOException("Error while decrypting block.").initCause(e);
86 }
87
88 internal_write(enc, 0, blockSize);
89 pos = 0;
90 }
91
92 public void write(byte[] src, int off, int len) throws IOException {
93 while (len > 0) {
94 int avail = blockSize - pos;
95 int copy = Math.min(avail, len);
96 System.arraycopy(src, off, buffer, pos, copy);
97 pos += copy;
98 off += copy;
99 len -= copy;
100
101 if (pos >= blockSize)
102 writeBlock();
103 }
104 }
105
106 public void write(int b) throws IOException {
107 buffer[pos++] = (byte) b;
108
109 if (pos >= blockSize)
110 writeBlock();
111 }
112
113 public void writePlain(int b) throws IOException {
114 if (pos != 0)
115 throw new IOException("Cannot write plain since crypto buffer is not aligned.");
116
117 internal_write(b);
118 }
119
120 public void writePlain(byte[] b, int off, int len) throws IOException {
121 if (pos != 0)
122 throw new IOException("Cannot write plain since crypto buffer is not aligned.");
123
124 internal_write(b, off, len);
125 }
126 }