mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-14 11:49:04 +01:00
The word "tag" was overloaded, so from now on use "tag" for the
predefined tags in the protocol and serial components, and "IV" for the encrypted IVs used to identify connections in the transport component.
This commit is contained in:
@@ -37,12 +37,12 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
private static final String KEY_PAIR_ALGO = "ECDSA";
|
||||
private static final int KEY_PAIR_BITS = 256;
|
||||
private static final String SECRET_STORAGE_ALGO = "AES/CTR/NoPadding";
|
||||
private static final String MAC_ALGO = "HMacSHA256";
|
||||
private static final String PACKET_CIPHER_ALGO = "AES/CTR/NoPadding";
|
||||
private static final String FRAME_CIPHER_ALGO = "AES/CTR/NoPadding";
|
||||
private static final String SECRET_KEY_ALGO = "AES";
|
||||
private static final int SECRET_KEY_BITS = 256;
|
||||
private static final String IV_CIPHER_ALGO = "AES/ECB/NoPadding";
|
||||
private static final String MAC_ALGO = "HMacSHA256";
|
||||
private static final String SIGNATURE_ALGO = "ECDSA";
|
||||
private static final String TAG_CIPHER_ALGO = "AES/ECB/NoPadding";
|
||||
|
||||
private final SecretKey secretStorageKey;
|
||||
private final KeyParser keyParser;
|
||||
@@ -68,14 +68,14 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
}
|
||||
}
|
||||
|
||||
public SecretKey deriveIncomingMacKey(byte[] secret) {
|
||||
public SecretKey deriveIncomingFrameKey(byte[] secret) {
|
||||
SharedSecret s = new SharedSecret(secret);
|
||||
return deriveMacKey(s, !s.getAlice());
|
||||
return deriveFrameKey(s, !s.getAlice());
|
||||
}
|
||||
|
||||
private SecretKey deriveMacKey(SharedSecret s, boolean alice) {
|
||||
if(alice) return deriveKey("MACA", s.getIv(), s.getCiphertext());
|
||||
else return deriveKey("MACB", s.getIv(), s.getCiphertext());
|
||||
private SecretKey deriveFrameKey(SharedSecret s, boolean alice) {
|
||||
if(alice) return deriveKey("F_A", s.getIv(), s.getCiphertext());
|
||||
else return deriveKey("F_B", s.getIv(), s.getCiphertext());
|
||||
}
|
||||
|
||||
private SecretKey deriveKey(String name, IvParameterSpec iv,
|
||||
@@ -114,29 +114,24 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
}
|
||||
}
|
||||
|
||||
public SecretKey deriveIncomingFrameKey(byte[] secret) {
|
||||
public SecretKey deriveIncomingIvKey(byte[] secret) {
|
||||
SharedSecret s = new SharedSecret(secret);
|
||||
return deriveFrameKey(s, !s.getAlice());
|
||||
return deriveIvKey(s, !s.getAlice());
|
||||
}
|
||||
|
||||
private SecretKey deriveFrameKey(SharedSecret s, boolean alice) {
|
||||
if(alice) return deriveKey("PKTA", s.getIv(), s.getCiphertext());
|
||||
else return deriveKey("PKTB", s.getIv(), s.getCiphertext());
|
||||
private SecretKey deriveIvKey(SharedSecret s, boolean alice) {
|
||||
if(alice) return deriveKey("I_A", s.getIv(), s.getCiphertext());
|
||||
else return deriveKey("I_B", s.getIv(), s.getCiphertext());
|
||||
}
|
||||
|
||||
public SecretKey deriveIncomingTagKey(byte[] secret) {
|
||||
public SecretKey deriveIncomingMacKey(byte[] secret) {
|
||||
SharedSecret s = new SharedSecret(secret);
|
||||
return deriveTagKey(s, !s.getAlice());
|
||||
return deriveMacKey(s, !s.getAlice());
|
||||
}
|
||||
|
||||
private SecretKey deriveTagKey(SharedSecret s, boolean alice) {
|
||||
if(alice) return deriveKey("TAGA", s.getIv(), s.getCiphertext());
|
||||
else return deriveKey("TAGB", s.getIv(), s.getCiphertext());
|
||||
}
|
||||
|
||||
public SecretKey deriveOutgoingMacKey(byte[] secret) {
|
||||
SharedSecret s = new SharedSecret(secret);
|
||||
return deriveMacKey(s, s.getAlice());
|
||||
private SecretKey deriveMacKey(SharedSecret s, boolean alice) {
|
||||
if(alice) return deriveKey("M_A", s.getIv(), s.getCiphertext());
|
||||
else return deriveKey("M_B", s.getIv(), s.getCiphertext());
|
||||
}
|
||||
|
||||
public SecretKey deriveOutgoingFrameKey(byte[] secret) {
|
||||
@@ -144,9 +139,14 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
return deriveFrameKey(s, s.getAlice());
|
||||
}
|
||||
|
||||
public SecretKey deriveOutgoingTagKey(byte[] secret) {
|
||||
public SecretKey deriveOutgoingIvKey(byte[] secret) {
|
||||
SharedSecret s = new SharedSecret(secret);
|
||||
return deriveTagKey(s, s.getAlice());
|
||||
return deriveIvKey(s, s.getAlice());
|
||||
}
|
||||
|
||||
public SecretKey deriveOutgoingMacKey(byte[] secret) {
|
||||
SharedSecret s = new SharedSecret(secret);
|
||||
return deriveMacKey(s, s.getAlice());
|
||||
}
|
||||
|
||||
public KeyPair generateKeyPair() {
|
||||
@@ -157,6 +157,30 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
return keyGenerator.generateKey();
|
||||
}
|
||||
|
||||
public Cipher getFrameCipher() {
|
||||
try {
|
||||
return Cipher.getInstance(FRAME_CIPHER_ALGO, PROVIDER);
|
||||
} catch(NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch(NoSuchPaddingException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch(NoSuchProviderException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Cipher getIvCipher() {
|
||||
try {
|
||||
return Cipher.getInstance(IV_CIPHER_ALGO, PROVIDER);
|
||||
} catch(NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch(NoSuchPaddingException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch(NoSuchProviderException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public KeyParser getKeyParser() {
|
||||
return keyParser;
|
||||
}
|
||||
@@ -181,18 +205,6 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
}
|
||||
}
|
||||
|
||||
public Cipher getFrameCipher() {
|
||||
try {
|
||||
return Cipher.getInstance(PACKET_CIPHER_ALGO, PROVIDER);
|
||||
} catch(NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch(NoSuchPaddingException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch(NoSuchProviderException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Signature getSignature() {
|
||||
try {
|
||||
return Signature.getInstance(SIGNATURE_ALGO, PROVIDER);
|
||||
@@ -202,16 +214,4 @@ class CryptoComponentImpl implements CryptoComponent {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Cipher getTagCipher() {
|
||||
try {
|
||||
return Cipher.getInstance(TAG_CIPHER_ALGO, PROVIDER);
|
||||
} catch(NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch(NoSuchPaddingException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch(NoSuchProviderException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||
import static net.sf.briar.api.transport.TransportConstants.IV_LENGTH;
|
||||
import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
|
||||
|
||||
import java.io.EOFException;
|
||||
@@ -24,7 +24,7 @@ implements ConnectionDecrypter {
|
||||
private final long connection;
|
||||
private final Cipher frameCipher;
|
||||
private final SecretKey frameKey;
|
||||
private final byte[] buf, tag;
|
||||
private final byte[] buf, iv;
|
||||
|
||||
private int bufOff = 0, bufLen = 0;
|
||||
private long frame = 0L;
|
||||
@@ -37,8 +37,8 @@ implements ConnectionDecrypter {
|
||||
this.connection = connection;
|
||||
this.frameCipher = frameCipher;
|
||||
this.frameKey = frameKey;
|
||||
buf = new byte[TAG_LENGTH];
|
||||
tag = new byte[TAG_LENGTH];
|
||||
buf = new byte[IV_LENGTH];
|
||||
iv = new byte[IV_LENGTH];
|
||||
}
|
||||
|
||||
public InputStream getInputStream() {
|
||||
@@ -132,11 +132,11 @@ implements ConnectionDecrypter {
|
||||
private void initialiseCipher() {
|
||||
assert betweenFrames;
|
||||
if(frame > MAX_32_BIT_UNSIGNED) throw new IllegalStateException();
|
||||
TagEncoder.encodeTag(tag, transportId, connection, frame);
|
||||
// Use the plaintext tag to initialise the packet cipher
|
||||
IvParameterSpec iv = new IvParameterSpec(tag);
|
||||
IvEncoder.encodeIv(iv, transportId, connection, frame);
|
||||
// Use the plaintext IV to initialise the frame cipher
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
||||
try {
|
||||
frameCipher.init(Cipher.DECRYPT_MODE, frameKey, iv);
|
||||
frameCipher.init(Cipher.DECRYPT_MODE, frameKey, ivSpec);
|
||||
} catch(InvalidAlgorithmParameterException badIv) {
|
||||
throw new RuntimeException(badIv);
|
||||
} catch(InvalidKeyException badKey) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||
import static net.sf.briar.api.transport.TransportConstants.IV_LENGTH;
|
||||
import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
|
||||
|
||||
import java.io.FilterOutputStream;
|
||||
@@ -20,29 +20,29 @@ implements ConnectionEncrypter {
|
||||
|
||||
private final int transportId;
|
||||
private final long connection;
|
||||
private final Cipher tagCipher, frameCipher;
|
||||
private final Cipher ivCipher, frameCipher;
|
||||
private final SecretKey frameKey;
|
||||
private final byte[] tag;
|
||||
private final byte[] iv;
|
||||
|
||||
private long frame = 0L;
|
||||
private boolean started = false, betweenFrames = false;
|
||||
|
||||
ConnectionEncrypterImpl(OutputStream out, int transportId,
|
||||
long connection, Cipher tagCipher, Cipher frameCipher,
|
||||
SecretKey tagKey, SecretKey frameKey) {
|
||||
long connection, Cipher ivCipher, Cipher frameCipher,
|
||||
SecretKey ivKey, SecretKey frameKey) {
|
||||
super(out);
|
||||
this.transportId = transportId;
|
||||
this.connection = connection;
|
||||
this.tagCipher = tagCipher;
|
||||
this.ivCipher = ivCipher;
|
||||
this.frameCipher = frameCipher;
|
||||
this.frameKey = frameKey;
|
||||
tag = new byte[TAG_LENGTH];
|
||||
iv = new byte[IV_LENGTH];
|
||||
try {
|
||||
tagCipher.init(Cipher.ENCRYPT_MODE, tagKey);
|
||||
ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
|
||||
} catch(InvalidKeyException badKey) {
|
||||
throw new IllegalArgumentException(badKey);
|
||||
}
|
||||
if(tagCipher.getOutputSize(TAG_LENGTH) != TAG_LENGTH)
|
||||
if(ivCipher.getOutputSize(IV_LENGTH) != IV_LENGTH)
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ implements ConnectionEncrypter {
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
if(!started) writeTag();
|
||||
if(!started) writeIv();
|
||||
if(betweenFrames) initialiseCipher();
|
||||
byte[] ciphertext = frameCipher.update(new byte[] {(byte) b});
|
||||
if(ciphertext != null) out.write(ciphertext);
|
||||
@@ -77,18 +77,18 @@ implements ConnectionEncrypter {
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
if(!started) writeTag();
|
||||
if(!started) writeIv();
|
||||
if(betweenFrames) initialiseCipher();
|
||||
byte[] ciphertext = frameCipher.update(b, off, len);
|
||||
if(ciphertext != null) out.write(ciphertext);
|
||||
}
|
||||
|
||||
private void writeTag() throws IOException {
|
||||
private void writeIv() throws IOException {
|
||||
assert !started;
|
||||
assert !betweenFrames;
|
||||
TagEncoder.encodeTag(tag, transportId, connection, 0L);
|
||||
IvEncoder.encodeIv(iv, transportId, connection, 0L);
|
||||
try {
|
||||
out.write(tagCipher.doFinal(tag));
|
||||
out.write(ivCipher.doFinal(iv));
|
||||
} catch(BadPaddingException badCipher) {
|
||||
throw new IOException(badCipher);
|
||||
} catch(IllegalBlockSizeException badCipher) {
|
||||
@@ -102,10 +102,10 @@ implements ConnectionEncrypter {
|
||||
assert started;
|
||||
assert betweenFrames;
|
||||
if(frame > MAX_32_BIT_UNSIGNED) throw new IllegalStateException();
|
||||
TagEncoder.encodeTag(tag, transportId, connection, frame);
|
||||
IvParameterSpec iv = new IvParameterSpec(tag);
|
||||
IvEncoder.encodeIv(iv, transportId, connection, frame);
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
||||
try {
|
||||
frameCipher.init(Cipher.ENCRYPT_MODE, frameKey, iv);
|
||||
frameCipher.init(Cipher.ENCRYPT_MODE, frameKey, ivSpec);
|
||||
} catch(InvalidAlgorithmParameterException badIv) {
|
||||
throw new RuntimeException(badIv);
|
||||
} catch(InvalidKeyException badKey) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||
import static net.sf.briar.api.transport.TransportConstants.IV_LENGTH;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.util.HashMap;
|
||||
@@ -27,9 +27,9 @@ DatabaseListener {
|
||||
private final int transportId;
|
||||
private final CryptoComponent crypto;
|
||||
private final DatabaseComponent db;
|
||||
private final Map<Bytes, ContactId> tagToContact;
|
||||
private final Map<Bytes, Long> tagToConnectionNumber;
|
||||
private final Map<ContactId, Map<Long, Bytes>> contactToTags;
|
||||
private final Map<Bytes, ContactId> ivToContact;
|
||||
private final Map<Bytes, Long> ivToConnectionNumber;
|
||||
private final Map<ContactId, Map<Long, Bytes>> contactToIvs;
|
||||
private final Map<ContactId, Cipher> contactToCipher;
|
||||
private final Map<ContactId, ConnectionWindow> contactToWindow;
|
||||
private boolean initialised = false;
|
||||
@@ -40,9 +40,9 @@ DatabaseListener {
|
||||
this.crypto = crypto;
|
||||
this.db = db;
|
||||
// FIXME: There's probably a tidier way of maintaining all this state
|
||||
tagToContact = new HashMap<Bytes, ContactId>();
|
||||
tagToConnectionNumber = new HashMap<Bytes, Long>();
|
||||
contactToTags = new HashMap<ContactId, Map<Long, Bytes>>();
|
||||
ivToContact = new HashMap<Bytes, ContactId>();
|
||||
ivToConnectionNumber = new HashMap<Bytes, Long>();
|
||||
contactToIvs = new HashMap<ContactId, Map<Long, Bytes>>();
|
||||
contactToCipher = new HashMap<ContactId, Cipher>();
|
||||
contactToWindow = new HashMap<ContactId, ConnectionWindow>();
|
||||
db.addListener(this);
|
||||
@@ -51,26 +51,26 @@ DatabaseListener {
|
||||
private synchronized void initialise() throws DbException {
|
||||
for(ContactId c : db.getContacts()) {
|
||||
try {
|
||||
// Initialise and store the contact's tag cipher
|
||||
// Initialise and store the contact's IV cipher
|
||||
byte[] secret = db.getSharedSecret(c);
|
||||
SecretKey tagKey = crypto.deriveIncomingTagKey(secret);
|
||||
Cipher cipher = crypto.getTagCipher();
|
||||
SecretKey ivKey = crypto.deriveIncomingIvKey(secret);
|
||||
Cipher cipher = crypto.getIvCipher();
|
||||
try {
|
||||
cipher.init(Cipher.ENCRYPT_MODE, tagKey);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, ivKey);
|
||||
} catch(InvalidKeyException badKey) {
|
||||
throw new RuntimeException(badKey);
|
||||
}
|
||||
contactToCipher.put(c, cipher);
|
||||
// Calculate the tags for the contact's connection window
|
||||
// Calculate the IVs for the contact's connection window
|
||||
ConnectionWindow w = db.getConnectionWindow(c, transportId);
|
||||
Map<Long, Bytes> tags = new HashMap<Long, Bytes>();
|
||||
Map<Long, Bytes> ivs = new HashMap<Long, Bytes>();
|
||||
for(Long unseen : w.getUnseenConnectionNumbers()) {
|
||||
Bytes expectedTag = new Bytes(calculateTag(c, unseen));
|
||||
tagToContact.put(expectedTag, c);
|
||||
tagToConnectionNumber.put(expectedTag, unseen);
|
||||
tags.put(unseen, expectedTag);
|
||||
Bytes expectedIv = new Bytes(encryptIv(c, unseen));
|
||||
ivToContact.put(expectedIv, c);
|
||||
ivToConnectionNumber.put(expectedIv, unseen);
|
||||
ivs.put(unseen, expectedIv);
|
||||
}
|
||||
contactToTags.put(c, tags);
|
||||
contactToIvs.put(c, ivs);
|
||||
contactToWindow.put(c, w);
|
||||
} catch(NoSuchContactException e) {
|
||||
// The contact was removed after the call to getContacts()
|
||||
@@ -80,12 +80,12 @@ DatabaseListener {
|
||||
initialised = true;
|
||||
}
|
||||
|
||||
private synchronized byte[] calculateTag(ContactId c, long connection) {
|
||||
byte[] tag = TagEncoder.encodeTag(transportId, connection);
|
||||
private synchronized byte[] encryptIv(ContactId c, long connection) {
|
||||
byte[] iv = IvEncoder.encodeIv(transportId, connection);
|
||||
Cipher cipher = contactToCipher.get(c);
|
||||
assert cipher != null;
|
||||
try {
|
||||
return cipher.doFinal(tag);
|
||||
return cipher.doFinal(iv);
|
||||
} catch(BadPaddingException badCipher) {
|
||||
throw new RuntimeException(badCipher);
|
||||
} catch(IllegalBlockSizeException badCipher) {
|
||||
@@ -93,36 +93,36 @@ DatabaseListener {
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized ContactId acceptConnection(byte[] tag)
|
||||
public synchronized ContactId acceptConnection(byte[] encryptedIv)
|
||||
throws DbException {
|
||||
if(tag.length != TAG_LENGTH)
|
||||
if(encryptedIv.length != IV_LENGTH)
|
||||
throw new IllegalArgumentException();
|
||||
if(!initialised) initialise();
|
||||
Bytes b = new Bytes(tag);
|
||||
ContactId contactId = tagToContact.remove(b);
|
||||
Long connection = tagToConnectionNumber.remove(b);
|
||||
Bytes b = new Bytes(encryptedIv);
|
||||
ContactId contactId = ivToContact.remove(b);
|
||||
Long connection = ivToConnectionNumber.remove(b);
|
||||
assert (contactId == null) == (connection == null);
|
||||
if(contactId == null) return null;
|
||||
// The tag was expected - update and save the connection window
|
||||
// The IV was expected - update and save the connection window
|
||||
ConnectionWindow w = contactToWindow.get(contactId);
|
||||
assert w != null;
|
||||
w.setSeen(connection);
|
||||
db.setConnectionWindow(contactId, transportId, w);
|
||||
// Update the set of expected tags
|
||||
Map<Long, Bytes> oldTags = contactToTags.remove(contactId);
|
||||
assert oldTags != null;
|
||||
assert oldTags.containsKey(connection);
|
||||
Map<Long, Bytes> newTags = new HashMap<Long, Bytes>();
|
||||
// Update the set of expected IVs
|
||||
Map<Long, Bytes> oldIvs = contactToIvs.remove(contactId);
|
||||
assert oldIvs != null;
|
||||
assert oldIvs.containsKey(connection);
|
||||
Map<Long, Bytes> newIvs = new HashMap<Long, Bytes>();
|
||||
for(Long unseen : w.getUnseenConnectionNumbers()) {
|
||||
Bytes expectedTag = oldTags.get(unseen);
|
||||
if(expectedTag == null) {
|
||||
expectedTag = new Bytes(calculateTag(contactId, unseen));
|
||||
tagToContact.put(expectedTag, contactId);
|
||||
tagToConnectionNumber.put(expectedTag, connection);
|
||||
Bytes expectedIv = oldIvs.get(unseen);
|
||||
if(expectedIv == null) {
|
||||
expectedIv = new Bytes(encryptIv(contactId, unseen));
|
||||
ivToContact.put(expectedIv, contactId);
|
||||
ivToConnectionNumber.put(expectedIv, connection);
|
||||
}
|
||||
newTags.put(unseen, expectedTag);
|
||||
newIvs.put(unseen, expectedIv);
|
||||
}
|
||||
contactToTags.put(contactId, newTags);
|
||||
contactToIvs.put(contactId, newIvs);
|
||||
return contactId;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
|
||||
public ConnectionWriter createConnectionWriter(OutputStream out,
|
||||
int transportId, long connection, byte[] secret) {
|
||||
SecretKey macKey = crypto.deriveOutgoingMacKey(secret);
|
||||
SecretKey tagKey = crypto.deriveOutgoingTagKey(secret);
|
||||
SecretKey ivKey = crypto.deriveOutgoingIvKey(secret);
|
||||
SecretKey frameKey = crypto.deriveOutgoingFrameKey(secret);
|
||||
Cipher tagCipher = crypto.getTagCipher();
|
||||
Cipher ivCipher = crypto.getIvCipher();
|
||||
Cipher frameCipher = crypto.getFrameCipher();
|
||||
Mac mac = crypto.getMac();
|
||||
try {
|
||||
@@ -36,7 +36,7 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
|
||||
throw new IllegalArgumentException(badKey);
|
||||
}
|
||||
ConnectionEncrypter encrypter = new ConnectionEncrypterImpl(out,
|
||||
transportId, connection, tagCipher, frameCipher, tagKey,
|
||||
transportId, connection, ivCipher, frameCipher, ivKey,
|
||||
frameKey);
|
||||
return new ConnectionWriterImpl(encrypter, mac);
|
||||
}
|
||||
|
||||
33
components/net/sf/briar/transport/IvEncoder.java
Normal file
33
components/net/sf/briar/transport/IvEncoder.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import static net.sf.briar.api.transport.TransportConstants.IV_LENGTH;
|
||||
import net.sf.briar.util.ByteUtils;
|
||||
|
||||
class IvEncoder {
|
||||
|
||||
static byte[] encodeIv(int transportId, long connection) {
|
||||
byte[] iv = new byte[IV_LENGTH];
|
||||
// Encode the transport identifier as an unsigned 16-bit integer
|
||||
ByteUtils.writeUint16(transportId, iv, 4);
|
||||
// Encode the connection number as an unsigned 32-bit integer
|
||||
ByteUtils.writeUint32(connection, iv, 6);
|
||||
return iv;
|
||||
}
|
||||
|
||||
static void encodeIv(byte[] iv, int transportId, long connection,
|
||||
long frame) {
|
||||
if(iv.length != IV_LENGTH) throw new IllegalArgumentException();
|
||||
// The first 16 bits of the IV must be zero (reserved)
|
||||
iv[0] = 0;
|
||||
iv[1] = 0;
|
||||
// Encode the transport identifier as an unsigned 16-bit integer
|
||||
ByteUtils.writeUint16(transportId, iv, 4);
|
||||
// Encode the connection number as an unsigned 32-bit integer
|
||||
ByteUtils.writeUint32(connection, iv, 6);
|
||||
// Encode the frame number as an unsigned 32-bit integer
|
||||
ByteUtils.writeUint32(frame, iv, 10);
|
||||
// The last 16 bits of the IV must be zero (block number)
|
||||
iv[14] = 0;
|
||||
iv[15] = 0;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||
import net.sf.briar.util.ByteUtils;
|
||||
|
||||
class TagDecoder {
|
||||
|
||||
static boolean decodeTag(byte[] tag, int transportId, long connection) {
|
||||
if(tag.length != TAG_LENGTH) return false;
|
||||
// First 32 bits must be zero (reserved)
|
||||
for(int i = 0; i < 4; i++) if(tag[i] != 0) return false;
|
||||
// Transport identifier is encoded as an unsigned 16-bit integer
|
||||
if(ByteUtils.readUint16(tag, 4) != transportId) return false;
|
||||
// Connection number is encoded as an unsigned 32-bit integer
|
||||
if(ByteUtils.readUint32(tag, 6) != connection) return false;
|
||||
// Last 48 bits must be zero (frame number and block number)
|
||||
for(int i = 10; i < 16; i++) if(tag[i] != 0) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package net.sf.briar.transport;
|
||||
|
||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||
import net.sf.briar.util.ByteUtils;
|
||||
|
||||
class TagEncoder {
|
||||
|
||||
static byte[] encodeTag(int transportId, long connection) {
|
||||
byte[] tag = new byte[TAG_LENGTH];
|
||||
// Encode the transport identifier as an unsigned 16-bit integer
|
||||
ByteUtils.writeUint16(transportId, tag, 4);
|
||||
// Encode the connection number as an unsigned 32-bit integer
|
||||
ByteUtils.writeUint32(connection, tag, 6);
|
||||
return tag;
|
||||
}
|
||||
|
||||
static void encodeTag(byte[] tag, int transportId, long connection,
|
||||
long frame) {
|
||||
if(tag.length != TAG_LENGTH) throw new IllegalArgumentException();
|
||||
// The first 16 bits of the tag must be zero (reserved)
|
||||
ByteUtils.writeUint16(0, tag, 0);
|
||||
// Encode the transport identifier as an unsigned 16-bit integer
|
||||
ByteUtils.writeUint16(transportId, tag, 4);
|
||||
// Encode the connection number as an unsigned 32-bit integer
|
||||
ByteUtils.writeUint32(connection, tag, 6);
|
||||
// Encode the frame number as an unsigned 32-bit integer
|
||||
ByteUtils.writeUint32(frame, tag, 10);
|
||||
// The last 16 bits of the tag must be zero (block number)
|
||||
ByteUtils.writeUint16(0, tag, 14);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user