blob: 0441eb6f8be478366fc8fa5453be81259d78e5e6 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package io.v.impl.google.lib.discovery;
import com.google.common.primitives.Bytes;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import io.v.v23.vom.BinaryUtil;
import io.v.x.ref.lib.discovery.EncryptionKey;
/**
* A utility to encode and decode fields in io.v.v23.Service fields for use in discovery.
*/
public class EncodingUtil {
static final Charset UTF8_CHARSET = Charset.forName("UTF-8");
/**
* Encodes the addresses passed in.
* @param addrs The list of addresses to encode.
* @return The byte representation of the encoded addresses.
* @throws IOException
*/
public static byte[] packAddresses(List<String> addrs) throws IOException {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
for (String addr : addrs) {
BinaryUtil.encodeUint(stream, addr.length());
stream.write(addr.getBytes(UTF8_CHARSET));
}
return stream.toByteArray();
}
/**
* Decodes addresses from a byte array that was encoded by packAddresses
* @param input The byte array toe decode
* @return The list of addresses.
* @throws IOException
*/
public static List<String> unpackAddresses(byte[] input) throws IOException {
ByteArrayInputStream stream = new ByteArrayInputStream(input);
List<String> output = new ArrayList<>();
while (stream.available() > 0) {
int stringSize = (int)BinaryUtil.decodeUint(stream);
byte[] data = new byte[stringSize];
int read = stream.read(data);
if (read != stringSize) {
throw new IOException("Unexpected end of stream while reading address");
}
output.add(new String(data, UTF8_CHARSET));
}
return output;
}
/**
* Encode the encryption keys and algorithm passed in.
* @param encryptionAlgorithm The encryption algorithm to use.
* See io.v.x.ref.lib.discovery.Constants for valid values.
* @param keys The keys to encode
* @return The byte array that is the encoded form.
* @throws IOException
*/
public static byte[] packEncryptionKeys(int encryptionAlgorithm, List<EncryptionKey> keys)
throws IOException {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
BinaryUtil.encodeUint(stream, encryptionAlgorithm);
for (EncryptionKey key : keys) {
byte[] byteKey = Bytes.toArray(key);
BinaryUtil.encodeUint(stream, byteKey.length);
stream.write(byteKey);
}
return stream.toByteArray();
}
/**
* Decodes the encryption algorithm and keys that was encoded by packEncryptionKeys.
* @param input The byte array containg the keys.
* @return The keys and the encryption algorithm in input.
* @throws IOException
*/
public static KeysAndAlgorithm unpackEncryptionKeys(byte[] input) throws IOException {
ByteArrayInputStream stream = new ByteArrayInputStream(input);
int algo = (int) BinaryUtil.decodeUint(stream);
List<EncryptionKey> keys = new ArrayList<>();
while (stream.available() > 0) {
int size = (int) BinaryUtil.decodeUint(stream);
byte[] key = new byte[size];
int read = stream.read(key);
if (read != size) {
throw new IOException("Unexpected end of file reading keys");
}
keys.add(new EncryptionKey(Bytes.asList(key)));
}
return new KeysAndAlgorithm(algo, keys);
}
/**
* An object with EncryptionKeys and the encryption algorithm.
*/
public static class KeysAndAlgorithm {
int encryptionAlgorithm;
List<EncryptionKey> keys;
/**
* Gets the stored encryption algorithm.
*/
public int getEncryptionAlgorithm() {
return encryptionAlgorithm;
}
/**
* Gets the stored keys.
*/
public List<EncryptionKey> getKeys() {
return keys;
}
KeysAndAlgorithm(int encryptionAlgo, List<EncryptionKey> keys) {
encryptionAlgorithm = encryptionAlgo;
this.keys = keys;
}
}
}