private static byte[] packList(Iterable<String> strings) { Buffer<?> buf = new Buffer.PlainBuffer(); for (String string : strings) { buf.putString(string); } return buf.getCompactData(); }
@Override public void compress(Buffer buffer) { deflater.setNextIn(buffer.array()); deflater.setNextInIndex(buffer.rpos()); deflater.setAvailIn(buffer.available()); buffer.wpos(buffer.rpos()); do { deflater.setNextOut(tempBuf); deflater.setNextOutIndex(0); deflater.setAvailOut(BUF_SIZE); final int status = deflater.deflate(JZlib.Z_PARTIAL_FLUSH); if (status == JZlib.Z_OK) { buffer.putRawBytes(tempBuf, 0, BUF_SIZE - deflater.getAvailOut()); } else { throw new SSHRuntimeException("compress: deflate returned " + status); } } while (deflater.getAvailOut() == 0); }
/** * Reads an SSH string * * @param cs the charset to use for decoding * * @return the string as a Java {@code String} */ public String readString(Charset cs) throws BufferException { int len = readUInt32AsInt(); if (len < 0 || len > 32768) { throw new BufferException("Bad item length: " + len); } ensureAvailable(len); String s = new String(data, rpos, len, cs); rpos += len; return s; }
/** * Writes Java byte-array as an SSH byte-array * * @param b Java byte-array * @param off offset * @param len length * * @return this */ public T putBytes(byte[] b, int off, int len) { return putUInt32(len).putRawBytes(b, off, len); }
/** * Copies the contents of provided buffer into this buffer * * @param buffer the {@code Buffer} to copy * * @return this */ @SuppressWarnings("unchecked") public T putBuffer(Buffer<? extends Buffer<?>> buffer) { if (buffer != null) { int r = buffer.available(); ensureCapacity(r); System.arraycopy(buffer.data, buffer.rpos, data, wpos, r); wpos += r; } return (T) this; }
static void writePubKeyContentsIntoBuffer(PublicKey publicKey, KeyType innerKeyType, Buffer<?> buf) { Certificate<PublicKey> certificate = toCertificate(publicKey); buf.putBytes(certificate.getNonce()); innerKeyType.writePubKeyContentsIntoBuffer(certificate.getKey(), buf); buf.putUInt64(certificate.getSerial()) .putUInt32(certificate.getType()) .putString(certificate.getId()) .putBytes(packList(certificate.getValidPrincipals())) .putUInt64(epochFromDate(certificate.getValidAfter())) .putUInt64(epochFromDate(certificate.getValidBefore())) .putBytes(packMap(certificate.getCritOptions())) .putBytes(packMap(certificate.getExtensions())) .putString("") // reserved .putBytes(certificate.getSignatureKey()) .putBytes(certificate.getSignature()); }
/** * Writes a char-array as an SSH string and then blanks it out. * <p/> * This is useful when a plaintext password needs to be sent. If {@code str} is {@code null}, an empty string is * written. * * @param str (null-ok) the string as a character array * * @return this */ @SuppressWarnings("unchecked") public T putSensitiveString(char[] str) { if (str == null) return putString(""); putUInt32(str.length); ensureCapacity(str.length); for (char c : str) data[wpos++] = (byte) c; Arrays.fill(str, ' '); return (T) this; }
@Test public void shouldCorrectlyEncodeAndDecodeUInt64Types() throws BufferException { // This number fits into a unsigned 64 bit integer but not a signed one. BigInteger bigUint64 = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE).add(BigInteger.ONE); assertEquals(0x8000000000000001l, bigUint64.longValue()); Buffer<PlainBuffer> buff = new PlainBuffer(); buff.putUInt64(bigUint64); byte[] data = buff.getCompactData(); assertEquals(8, data.length); assertEquals((byte) 0x80, data[0]); assertEquals((byte) 0x00, data[1]); assertEquals((byte) 0x00, data[2]); assertEquals((byte) 0x00, data[3]); assertEquals((byte) 0x00, data[4]); assertEquals((byte) 0x00, data[5]); assertEquals((byte) 0x00, data[6]); assertEquals((byte) 0x01, data[7]); byte[] asBinary = new byte[] { (byte) 0x80, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01 }; buff = new PlainBuffer(asBinary); assertEquals(bigUint64, buff.readUInt64AsBigInteger()); }
private static Map<String, String> unpackMap(byte[] packedString) throws BufferException { Map<String, String> map = new LinkedHashMap<String, String>(); Buffer<?> buf = new Buffer.PlainBuffer(packedString); while (buf.available() > 0) { String name = buf.readString(); String data = unpackString(buf.readStringAsBytes()); map.put(name, data); } return map; }
public void wpos(int wpos) { ensureCapacity(wpos - this.wpos); this.wpos = wpos; }
/** * Writes Java byte-array as an SSH byte-array * * @param b Java byte-array * * @return this */ public T putBytes(byte[] b) { return putBytes(b, 0, b.length); }
@Override public void putPubKeyIntoBuffer(PublicKey pk, Buffer<?> buf) { final ECPublicKey ecdsa = (ECPublicKey) pk; final java.security.spec.ECPoint point = ecdsa.getW(); final byte[] x = trimStartingZeros(point.getAffineX().toByteArray()); final byte[] y = trimStartingZeros(point.getAffineY().toByteArray()); buf.putString(sType) .putString(NISTP_CURVE) .putUInt32(1 + x.length + y.length) .putRawBytes(new byte[] { (byte) 0x04 }) .putRawBytes(x) .putRawBytes(y) ; }
/** Compact this {@link SSHPacket} */ public void compact() { if (available() > 0) System.arraycopy(data, rpos, data, 0, wpos - rpos); wpos -= rpos; rpos = 0; }
public long readUInt32() throws BufferException { ensureAvailable(4); return data[rpos++] << 24 & 0xff000000L | data[rpos++] << 16 & 0x00ff0000L | data[rpos++] << 8 & 0x0000ff00L | data[rpos++] & 0x000000ffL; }
private static List<String> unpackList(byte[] packedString) throws BufferException { List<String> list = new ArrayList<String>(); Buffer<?> buf = new Buffer.PlainBuffer(packedString); while (buf.available() > 0) { list.add(buf.readString()); } return list; }
public Buffer(int size) { this(new byte[getNextPowerOf2(size)], false); }
@Override public byte[] encode(byte[] sig) { int rIndex = 3; int rLen = sig[rIndex++] & 0xff; byte[] r = new byte[rLen]; System.arraycopy(sig, rIndex, r, 0, r.length); int sIndex = rIndex + rLen + 1; int sLen = sig[sIndex++] & 0xff; byte[] s = new byte[sLen]; System.arraycopy(sig, sIndex, s, 0, s.length); System.arraycopy(sig, 4, r, 0, rLen); System.arraycopy(sig, 6 + rLen, s, 0, sLen); Buffer buf = new Buffer.PlainBuffer(); buf.putMPInt(new BigInteger(r)); buf.putMPInt(new BigInteger(s)); return buf.getCompactData(); }