mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-21 07:09:56 +01:00
Made secret keys erasable from memory.
This commit is contained in:
@@ -6,26 +6,23 @@ import java.security.Signature;
|
|||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.Mac;
|
import javax.crypto.Mac;
|
||||||
import javax.crypto.SecretKey;
|
|
||||||
|
|
||||||
public interface CryptoComponent {
|
public interface CryptoComponent {
|
||||||
|
|
||||||
SecretKey deriveIncomingFrameKey(byte[] secret);
|
ErasableKey deriveIncomingFrameKey(byte[] secret);
|
||||||
|
|
||||||
SecretKey deriveIncomingIvKey(byte[] secret);
|
ErasableKey deriveIncomingIvKey(byte[] secret);
|
||||||
|
|
||||||
SecretKey deriveIncomingMacKey(byte[] secret);
|
ErasableKey deriveIncomingMacKey(byte[] secret);
|
||||||
|
|
||||||
SecretKey deriveOutgoingFrameKey(byte[] secret);
|
ErasableKey deriveOutgoingFrameKey(byte[] secret);
|
||||||
|
|
||||||
SecretKey deriveOutgoingIvKey(byte[] secret);
|
ErasableKey deriveOutgoingIvKey(byte[] secret);
|
||||||
|
|
||||||
SecretKey deriveOutgoingMacKey(byte[] secret);
|
ErasableKey deriveOutgoingMacKey(byte[] secret);
|
||||||
|
|
||||||
KeyPair generateKeyPair();
|
KeyPair generateKeyPair();
|
||||||
|
|
||||||
SecretKey generateSecretKey();
|
|
||||||
|
|
||||||
Cipher getFrameCipher();
|
Cipher getFrameCipher();
|
||||||
|
|
||||||
Cipher getIvCipher();
|
Cipher getIvCipher();
|
||||||
@@ -39,4 +36,6 @@ public interface CryptoComponent {
|
|||||||
SecureRandom getSecureRandom();
|
SecureRandom getSecureRandom();
|
||||||
|
|
||||||
Signature getSignature();
|
Signature getSignature();
|
||||||
|
|
||||||
|
ErasableKey generateTestKey();
|
||||||
}
|
}
|
||||||
|
|||||||
9
api/net/sf/briar/api/crypto/ErasableKey.java
Normal file
9
api/net/sf/briar/api/crypto/ErasableKey.java
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package net.sf.briar.api.crypto;
|
||||||
|
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
|
||||||
|
public interface ErasableKey extends SecretKey {
|
||||||
|
|
||||||
|
/** Erases the key from memory. */
|
||||||
|
void erase();
|
||||||
|
}
|
||||||
@@ -10,13 +10,11 @@ import java.security.Security;
|
|||||||
import java.security.Signature;
|
import java.security.Signature;
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.KeyGenerator;
|
|
||||||
import javax.crypto.Mac;
|
import javax.crypto.Mac;
|
||||||
import javax.crypto.NoSuchPaddingException;
|
import javax.crypto.NoSuchPaddingException;
|
||||||
import javax.crypto.SecretKey;
|
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
|
||||||
|
|
||||||
import net.sf.briar.api.crypto.CryptoComponent;
|
import net.sf.briar.api.crypto.CryptoComponent;
|
||||||
|
import net.sf.briar.api.crypto.ErasableKey;
|
||||||
import net.sf.briar.api.crypto.KeyParser;
|
import net.sf.briar.api.crypto.KeyParser;
|
||||||
import net.sf.briar.api.crypto.MessageDigest;
|
import net.sf.briar.api.crypto.MessageDigest;
|
||||||
|
|
||||||
@@ -32,14 +30,13 @@ class CryptoComponentImpl implements CryptoComponent {
|
|||||||
private static final int KEY_PAIR_BITS = 256;
|
private static final int KEY_PAIR_BITS = 256;
|
||||||
private static final String FRAME_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 String SECRET_KEY_ALGO = "AES";
|
||||||
private static final int SECRET_KEY_BITS = 256;
|
private static final int SECRET_KEY_BYTES = 32;
|
||||||
private static final String IV_CIPHER_ALGO = "AES/ECB/NoPadding";
|
private static final String IV_CIPHER_ALGO = "AES/ECB/NoPadding";
|
||||||
private static final String MAC_ALGO = "HMacSHA256";
|
private static final String MAC_ALGO = "HMacSHA256";
|
||||||
private static final String SIGNATURE_ALGO = "ECDSA";
|
private static final String SIGNATURE_ALGO = "ECDSA";
|
||||||
|
|
||||||
private final KeyParser keyParser;
|
private final KeyParser keyParser;
|
||||||
private final KeyPairGenerator keyPairGenerator;
|
private final KeyPairGenerator keyPairGenerator;
|
||||||
private final KeyGenerator keyGenerator;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
CryptoComponentImpl() {
|
CryptoComponentImpl() {
|
||||||
@@ -49,9 +46,6 @@ class CryptoComponentImpl implements CryptoComponent {
|
|||||||
keyPairGenerator = KeyPairGenerator.getInstance(KEY_PAIR_ALGO,
|
keyPairGenerator = KeyPairGenerator.getInstance(KEY_PAIR_ALGO,
|
||||||
PROVIDER);
|
PROVIDER);
|
||||||
keyPairGenerator.initialize(KEY_PAIR_BITS);
|
keyPairGenerator.initialize(KEY_PAIR_BITS);
|
||||||
keyGenerator = KeyGenerator.getInstance(SECRET_KEY_ALGO,
|
|
||||||
PROVIDER);
|
|
||||||
keyGenerator.init(SECRET_KEY_BITS);
|
|
||||||
} catch(NoSuchAlgorithmException e) {
|
} catch(NoSuchAlgorithmException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
} catch(NoSuchProviderException e) {
|
} catch(NoSuchProviderException e) {
|
||||||
@@ -59,58 +53,59 @@ class CryptoComponentImpl implements CryptoComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SecretKey deriveIncomingFrameKey(byte[] secret) {
|
public ErasableKey deriveIncomingFrameKey(byte[] secret) {
|
||||||
SharedSecret s = new SharedSecret(secret);
|
SharedSecret s = new SharedSecret(secret);
|
||||||
return deriveFrameKey(s, !s.getAlice());
|
return deriveFrameKey(s, !s.getAlice());
|
||||||
}
|
}
|
||||||
|
|
||||||
private SecretKey deriveFrameKey(SharedSecret s, boolean alice) {
|
private ErasableKey deriveFrameKey(SharedSecret s, boolean alice) {
|
||||||
if(alice) return deriveKey("F_A", s.getSecret());
|
if(alice) return deriveKey("F_A", s.getSecret());
|
||||||
else return deriveKey("F_B", s.getSecret());
|
else return deriveKey("F_B", s.getSecret());
|
||||||
}
|
}
|
||||||
|
|
||||||
private SecretKey deriveKey(String name, byte[] secret) {
|
private ErasableKey deriveKey(String name, byte[] secret) {
|
||||||
MessageDigest digest = getMessageDigest();
|
MessageDigest digest = getMessageDigest();
|
||||||
|
assert digest.getDigestLength() == SECRET_KEY_BYTES;
|
||||||
try {
|
try {
|
||||||
digest.update(name.getBytes("UTF-8"));
|
digest.update(name.getBytes("UTF-8"));
|
||||||
} catch(UnsupportedEncodingException e) {
|
} catch(UnsupportedEncodingException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
digest.update(secret);
|
digest.update(secret);
|
||||||
return new SecretKeySpec(digest.digest(), SECRET_KEY_ALGO);
|
return new ErasableKeyImpl(digest.digest(), SECRET_KEY_ALGO);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SecretKey deriveIncomingIvKey(byte[] secret) {
|
public ErasableKey deriveIncomingIvKey(byte[] secret) {
|
||||||
SharedSecret s = new SharedSecret(secret);
|
SharedSecret s = new SharedSecret(secret);
|
||||||
return deriveIvKey(s, !s.getAlice());
|
return deriveIvKey(s, !s.getAlice());
|
||||||
}
|
}
|
||||||
|
|
||||||
private SecretKey deriveIvKey(SharedSecret s, boolean alice) {
|
private ErasableKey deriveIvKey(SharedSecret s, boolean alice) {
|
||||||
if(alice) return deriveKey("I_A", s.getSecret());
|
if(alice) return deriveKey("I_A", s.getSecret());
|
||||||
else return deriveKey("I_B", s.getSecret());
|
else return deriveKey("I_B", s.getSecret());
|
||||||
}
|
}
|
||||||
|
|
||||||
public SecretKey deriveIncomingMacKey(byte[] secret) {
|
public ErasableKey deriveIncomingMacKey(byte[] secret) {
|
||||||
SharedSecret s = new SharedSecret(secret);
|
SharedSecret s = new SharedSecret(secret);
|
||||||
return deriveMacKey(s, !s.getAlice());
|
return deriveMacKey(s, !s.getAlice());
|
||||||
}
|
}
|
||||||
|
|
||||||
private SecretKey deriveMacKey(SharedSecret s, boolean alice) {
|
private ErasableKey deriveMacKey(SharedSecret s, boolean alice) {
|
||||||
if(alice) return deriveKey("M_A", s.getSecret());
|
if(alice) return deriveKey("M_A", s.getSecret());
|
||||||
else return deriveKey("M_B", s.getSecret());
|
else return deriveKey("M_B", s.getSecret());
|
||||||
}
|
}
|
||||||
|
|
||||||
public SecretKey deriveOutgoingFrameKey(byte[] secret) {
|
public ErasableKey deriveOutgoingFrameKey(byte[] secret) {
|
||||||
SharedSecret s = new SharedSecret(secret);
|
SharedSecret s = new SharedSecret(secret);
|
||||||
return deriveFrameKey(s, s.getAlice());
|
return deriveFrameKey(s, s.getAlice());
|
||||||
}
|
}
|
||||||
|
|
||||||
public SecretKey deriveOutgoingIvKey(byte[] secret) {
|
public ErasableKey deriveOutgoingIvKey(byte[] secret) {
|
||||||
SharedSecret s = new SharedSecret(secret);
|
SharedSecret s = new SharedSecret(secret);
|
||||||
return deriveIvKey(s, s.getAlice());
|
return deriveIvKey(s, s.getAlice());
|
||||||
}
|
}
|
||||||
|
|
||||||
public SecretKey deriveOutgoingMacKey(byte[] secret) {
|
public ErasableKey deriveOutgoingMacKey(byte[] secret) {
|
||||||
SharedSecret s = new SharedSecret(secret);
|
SharedSecret s = new SharedSecret(secret);
|
||||||
return deriveMacKey(s, s.getAlice());
|
return deriveMacKey(s, s.getAlice());
|
||||||
}
|
}
|
||||||
@@ -119,10 +114,6 @@ class CryptoComponentImpl implements CryptoComponent {
|
|||||||
return keyPairGenerator.generateKeyPair();
|
return keyPairGenerator.generateKeyPair();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SecretKey generateSecretKey() {
|
|
||||||
return keyGenerator.generateKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Cipher getFrameCipher() {
|
public Cipher getFrameCipher() {
|
||||||
try {
|
try {
|
||||||
return Cipher.getInstance(FRAME_CIPHER_ALGO, PROVIDER);
|
return Cipher.getInstance(FRAME_CIPHER_ALGO, PROVIDER);
|
||||||
@@ -186,4 +177,10 @@ class CryptoComponentImpl implements CryptoComponent {
|
|||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ErasableKey generateTestKey() {
|
||||||
|
byte[] b = new byte[SECRET_KEY_BYTES];
|
||||||
|
getSecureRandom().nextBytes(b);
|
||||||
|
return new ErasableKeyImpl(b, SECRET_KEY_ALGO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
55
components/net/sf/briar/crypto/ErasableKeyImpl.java
Normal file
55
components/net/sf/briar/crypto/ErasableKeyImpl.java
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package net.sf.briar.crypto;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import net.sf.briar.api.crypto.ErasableKey;
|
||||||
|
|
||||||
|
class ErasableKeyImpl implements ErasableKey {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -4438380720846443120L;
|
||||||
|
|
||||||
|
private final byte[] key;
|
||||||
|
private final String algorithm;
|
||||||
|
private boolean erased = false;
|
||||||
|
|
||||||
|
ErasableKeyImpl(byte[] key, String algorithm) {
|
||||||
|
this.key = key;
|
||||||
|
this.algorithm = algorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAlgorithm() {
|
||||||
|
return algorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getEncoded() {
|
||||||
|
if(erased) throw new IllegalStateException();
|
||||||
|
byte[] b = new byte[key.length];
|
||||||
|
System.arraycopy(key, 0, b, 0, key.length);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFormat() {
|
||||||
|
return "RAW";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void erase() {
|
||||||
|
if(erased) throw new IllegalStateException();
|
||||||
|
for(int i = 0; i < key.length; i++) key[i] = 0;
|
||||||
|
erased = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
// Not good, but the array can't be used because it's mutable
|
||||||
|
return algorithm.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if(o instanceof ErasableKeyImpl) {
|
||||||
|
ErasableKeyImpl e = (ErasableKeyImpl) o;
|
||||||
|
return algorithm.equals(e.algorithm) && Arrays.equals(key, e.key);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,7 +13,7 @@ import java.security.InvalidKeyException;
|
|||||||
import javax.crypto.BadPaddingException;
|
import javax.crypto.BadPaddingException;
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.IllegalBlockSizeException;
|
import javax.crypto.IllegalBlockSizeException;
|
||||||
import javax.crypto.SecretKey;
|
import net.sf.briar.api.crypto.ErasableKey;
|
||||||
import javax.crypto.ShortBufferException;
|
import javax.crypto.ShortBufferException;
|
||||||
import javax.crypto.spec.IvParameterSpec;
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ class ConnectionDecrypterImpl extends FilterInputStream
|
|||||||
implements ConnectionDecrypter {
|
implements ConnectionDecrypter {
|
||||||
|
|
||||||
private final Cipher frameCipher;
|
private final Cipher frameCipher;
|
||||||
private final SecretKey frameKey;
|
private final ErasableKey frameKey;
|
||||||
private final byte[] iv, buf;
|
private final byte[] iv, buf;
|
||||||
|
|
||||||
private int bufOff = 0, bufLen = 0;
|
private int bufOff = 0, bufLen = 0;
|
||||||
@@ -29,7 +29,7 @@ implements ConnectionDecrypter {
|
|||||||
private boolean betweenFrames = true;
|
private boolean betweenFrames = true;
|
||||||
|
|
||||||
ConnectionDecrypterImpl(InputStream in, byte[] iv, Cipher frameCipher,
|
ConnectionDecrypterImpl(InputStream in, byte[] iv, Cipher frameCipher,
|
||||||
SecretKey frameKey) {
|
ErasableKey frameKey) {
|
||||||
super(in);
|
super(in);
|
||||||
if(iv.length != IV_LENGTH) throw new IllegalArgumentException();
|
if(iv.length != IV_LENGTH) throw new IllegalArgumentException();
|
||||||
this.iv = iv;
|
this.iv = iv;
|
||||||
|
|||||||
@@ -12,22 +12,22 @@ import java.security.InvalidKeyException;
|
|||||||
import javax.crypto.BadPaddingException;
|
import javax.crypto.BadPaddingException;
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.IllegalBlockSizeException;
|
import javax.crypto.IllegalBlockSizeException;
|
||||||
import javax.crypto.SecretKey;
|
import net.sf.briar.api.crypto.ErasableKey;
|
||||||
import javax.crypto.spec.IvParameterSpec;
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
|
|
||||||
class ConnectionEncrypterImpl extends FilterOutputStream
|
class ConnectionEncrypterImpl extends FilterOutputStream
|
||||||
implements ConnectionEncrypter {
|
implements ConnectionEncrypter {
|
||||||
|
|
||||||
private final Cipher frameCipher;
|
private final Cipher frameCipher;
|
||||||
private final SecretKey frameKey;
|
private final ErasableKey frameKey;
|
||||||
private final byte[] iv, encryptedIv;
|
private final byte[] iv, encryptedIv;
|
||||||
|
|
||||||
private long capacity, frame = 0L;
|
private long capacity, frame = 0L;
|
||||||
private boolean ivWritten = false, betweenFrames = false;
|
private boolean ivWritten = false, betweenFrames = false;
|
||||||
|
|
||||||
ConnectionEncrypterImpl(OutputStream out, long capacity, byte[] iv,
|
ConnectionEncrypterImpl(OutputStream out, long capacity, byte[] iv,
|
||||||
Cipher ivCipher, Cipher frameCipher, SecretKey ivKey,
|
Cipher ivCipher, Cipher frameCipher, ErasableKey ivKey,
|
||||||
SecretKey frameKey) {
|
ErasableKey frameKey) {
|
||||||
super(out);
|
super(out);
|
||||||
this.capacity = capacity;
|
this.capacity = capacity;
|
||||||
this.iv = iv;
|
this.iv = iv;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import javax.crypto.BadPaddingException;
|
|||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.IllegalBlockSizeException;
|
import javax.crypto.IllegalBlockSizeException;
|
||||||
import javax.crypto.Mac;
|
import javax.crypto.Mac;
|
||||||
import javax.crypto.SecretKey;
|
import net.sf.briar.api.crypto.ErasableKey;
|
||||||
|
|
||||||
import net.sf.briar.api.crypto.CryptoComponent;
|
import net.sf.briar.api.crypto.CryptoComponent;
|
||||||
import net.sf.briar.api.protocol.TransportIndex;
|
import net.sf.briar.api.protocol.TransportIndex;
|
||||||
@@ -29,7 +29,7 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory {
|
|||||||
TransportIndex i, byte[] encryptedIv, byte[] secret) {
|
TransportIndex i, byte[] encryptedIv, byte[] secret) {
|
||||||
// Decrypt the IV
|
// Decrypt the IV
|
||||||
Cipher ivCipher = crypto.getIvCipher();
|
Cipher ivCipher = crypto.getIvCipher();
|
||||||
SecretKey ivKey = crypto.deriveIncomingIvKey(secret);
|
ErasableKey ivKey = crypto.deriveIncomingIvKey(secret);
|
||||||
byte[] iv;
|
byte[] iv;
|
||||||
try {
|
try {
|
||||||
ivCipher.init(Cipher.DECRYPT_MODE, ivKey);
|
ivCipher.init(Cipher.DECRYPT_MODE, ivKey);
|
||||||
@@ -60,12 +60,12 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory {
|
|||||||
byte[] iv = IvEncoder.encodeIv(initiator, i, connection);
|
byte[] iv = IvEncoder.encodeIv(initiator, i, connection);
|
||||||
// Create the decrypter
|
// Create the decrypter
|
||||||
Cipher frameCipher = crypto.getFrameCipher();
|
Cipher frameCipher = crypto.getFrameCipher();
|
||||||
SecretKey frameKey = crypto.deriveIncomingFrameKey(secret);
|
ErasableKey frameKey = crypto.deriveIncomingFrameKey(secret);
|
||||||
ConnectionDecrypter decrypter = new ConnectionDecrypterImpl(in, iv,
|
ConnectionDecrypter decrypter = new ConnectionDecrypterImpl(in, iv,
|
||||||
frameCipher, frameKey);
|
frameCipher, frameKey);
|
||||||
// Create the reader
|
// Create the reader
|
||||||
Mac mac = crypto.getMac();
|
Mac mac = crypto.getMac();
|
||||||
SecretKey macKey = crypto.deriveIncomingMacKey(secret);
|
ErasableKey macKey = crypto.deriveIncomingMacKey(secret);
|
||||||
return new ConnectionReaderImpl(decrypter, mac, macKey);
|
return new ConnectionReaderImpl(decrypter, mac, macKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import java.security.InvalidKeyException;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import javax.crypto.Mac;
|
import javax.crypto.Mac;
|
||||||
import javax.crypto.SecretKey;
|
import net.sf.briar.api.crypto.ErasableKey;
|
||||||
|
|
||||||
import net.sf.briar.api.FormatException;
|
import net.sf.briar.api.FormatException;
|
||||||
import net.sf.briar.api.transport.ConnectionReader;
|
import net.sf.briar.api.transport.ConnectionReader;
|
||||||
@@ -30,7 +30,7 @@ implements ConnectionReader {
|
|||||||
private boolean betweenFrames = true;
|
private boolean betweenFrames = true;
|
||||||
|
|
||||||
ConnectionReaderImpl(ConnectionDecrypter decrypter, Mac mac,
|
ConnectionReaderImpl(ConnectionDecrypter decrypter, Mac mac,
|
||||||
SecretKey macKey) {
|
ErasableKey macKey) {
|
||||||
super(decrypter.getInputStream());
|
super(decrypter.getInputStream());
|
||||||
this.decrypter = decrypter;
|
this.decrypter = decrypter;
|
||||||
this.mac = mac;
|
this.mac = mac;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import java.util.logging.Logger;
|
|||||||
import javax.crypto.BadPaddingException;
|
import javax.crypto.BadPaddingException;
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.IllegalBlockSizeException;
|
import javax.crypto.IllegalBlockSizeException;
|
||||||
import javax.crypto.SecretKey;
|
import net.sf.briar.api.crypto.ErasableKey;
|
||||||
|
|
||||||
import net.sf.briar.api.Bytes;
|
import net.sf.briar.api.Bytes;
|
||||||
import net.sf.briar.api.ContactId;
|
import net.sf.briar.api.ContactId;
|
||||||
@@ -75,7 +75,7 @@ DatabaseListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void calculateIvs(ContactId c) throws DbException {
|
private synchronized void calculateIvs(ContactId c) throws DbException {
|
||||||
SecretKey ivKey = crypto.deriveIncomingIvKey(db.getSharedSecret(c));
|
ErasableKey ivKey = crypto.deriveIncomingIvKey(db.getSharedSecret(c));
|
||||||
for(TransportId t : localTransportIds) {
|
for(TransportId t : localTransportIds) {
|
||||||
TransportIndex i = db.getRemoteIndex(c, t);
|
TransportIndex i = db.getRemoteIndex(c, t);
|
||||||
if(i != null) {
|
if(i != null) {
|
||||||
@@ -86,7 +86,7 @@ DatabaseListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void calculateIvs(ContactId c, TransportId t,
|
private synchronized void calculateIvs(ContactId c, TransportId t,
|
||||||
TransportIndex i, SecretKey ivKey, ConnectionWindow w)
|
TransportIndex i, ErasableKey ivKey, ConnectionWindow w)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
for(Long unseen : w.getUnseen()) {
|
for(Long unseen : w.getUnseen()) {
|
||||||
Bytes iv = new Bytes(encryptIv(i, unseen, ivKey));
|
Bytes iv = new Bytes(encryptIv(i, unseen, ivKey));
|
||||||
@@ -95,7 +95,7 @@ DatabaseListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private synchronized byte[] encryptIv(TransportIndex i, long connection,
|
private synchronized byte[] encryptIv(TransportIndex i, long connection,
|
||||||
SecretKey ivKey) {
|
ErasableKey ivKey) {
|
||||||
byte[] iv = IvEncoder.encodeIv(true, i, connection);
|
byte[] iv = IvEncoder.encodeIv(true, i, connection);
|
||||||
try {
|
try {
|
||||||
ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
|
ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
|
||||||
@@ -131,7 +131,7 @@ DatabaseListener {
|
|||||||
TransportIndex i1 = ctx1.getTransportIndex();
|
TransportIndex i1 = ctx1.getTransportIndex();
|
||||||
if(c1.equals(c) && i1.equals(i)) it.remove();
|
if(c1.equals(c) && i1.equals(i)) it.remove();
|
||||||
}
|
}
|
||||||
SecretKey ivKey = crypto.deriveIncomingIvKey(db.getSharedSecret(c));
|
ErasableKey ivKey = crypto.deriveIncomingIvKey(db.getSharedSecret(c));
|
||||||
calculateIvs(c, ctx.getTransportId(), i, ivKey, w);
|
calculateIvs(c, ctx.getTransportId(), i, ivKey, w);
|
||||||
} catch(NoSuchContactException e) {
|
} catch(NoSuchContactException e) {
|
||||||
// The contact was removed - clean up when we get the event
|
// The contact was removed - clean up when we get the event
|
||||||
@@ -182,7 +182,7 @@ DatabaseListener {
|
|||||||
for(ContactId c : db.getContacts()) {
|
for(ContactId c : db.getContacts()) {
|
||||||
try {
|
try {
|
||||||
byte[] secret = db.getSharedSecret(c);
|
byte[] secret = db.getSharedSecret(c);
|
||||||
SecretKey ivKey = crypto.deriveIncomingIvKey(secret);
|
ErasableKey ivKey = crypto.deriveIncomingIvKey(secret);
|
||||||
TransportIndex i = db.getRemoteIndex(c, t);
|
TransportIndex i = db.getRemoteIndex(c, t);
|
||||||
if(i != null) {
|
if(i != null) {
|
||||||
ConnectionWindow w = db.getConnectionWindow(c, i);
|
ConnectionWindow w = db.getConnectionWindow(c, i);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import javax.crypto.BadPaddingException;
|
|||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.IllegalBlockSizeException;
|
import javax.crypto.IllegalBlockSizeException;
|
||||||
import javax.crypto.Mac;
|
import javax.crypto.Mac;
|
||||||
import javax.crypto.SecretKey;
|
import net.sf.briar.api.crypto.ErasableKey;
|
||||||
|
|
||||||
import net.sf.briar.api.crypto.CryptoComponent;
|
import net.sf.briar.api.crypto.CryptoComponent;
|
||||||
import net.sf.briar.api.protocol.TransportIndex;
|
import net.sf.briar.api.protocol.TransportIndex;
|
||||||
@@ -36,7 +36,7 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
|
|||||||
byte[] secret) {
|
byte[] secret) {
|
||||||
// Decrypt the IV
|
// Decrypt the IV
|
||||||
Cipher ivCipher = crypto.getIvCipher();
|
Cipher ivCipher = crypto.getIvCipher();
|
||||||
SecretKey ivKey = crypto.deriveIncomingIvKey(secret);
|
ErasableKey ivKey = crypto.deriveIncomingIvKey(secret);
|
||||||
byte[] iv;
|
byte[] iv;
|
||||||
try {
|
try {
|
||||||
ivCipher.init(Cipher.DECRYPT_MODE, ivKey);
|
ivCipher.init(Cipher.DECRYPT_MODE, ivKey);
|
||||||
@@ -63,14 +63,14 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
|
|||||||
// Create the encrypter
|
// Create the encrypter
|
||||||
Cipher ivCipher = crypto.getIvCipher();
|
Cipher ivCipher = crypto.getIvCipher();
|
||||||
Cipher frameCipher = crypto.getFrameCipher();
|
Cipher frameCipher = crypto.getFrameCipher();
|
||||||
SecretKey ivKey = crypto.deriveOutgoingIvKey(secret);
|
ErasableKey ivKey = crypto.deriveOutgoingIvKey(secret);
|
||||||
SecretKey frameKey = crypto.deriveOutgoingFrameKey(secret);
|
ErasableKey frameKey = crypto.deriveOutgoingFrameKey(secret);
|
||||||
byte[] iv = IvEncoder.encodeIv(initiator, i, connection);
|
byte[] iv = IvEncoder.encodeIv(initiator, i, connection);
|
||||||
ConnectionEncrypter encrypter = new ConnectionEncrypterImpl(out,
|
ConnectionEncrypter encrypter = new ConnectionEncrypterImpl(out,
|
||||||
capacity, iv, ivCipher, frameCipher, ivKey, frameKey);
|
capacity, iv, ivCipher, frameCipher, ivKey, frameKey);
|
||||||
// Create the writer
|
// Create the writer
|
||||||
Mac mac = crypto.getMac();
|
Mac mac = crypto.getMac();
|
||||||
SecretKey macKey = crypto.deriveOutgoingMacKey(secret);
|
ErasableKey macKey = crypto.deriveOutgoingMacKey(secret);
|
||||||
return new ConnectionWriterImpl(encrypter, mac, macKey);
|
return new ConnectionWriterImpl(encrypter, mac, macKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import java.io.OutputStream;
|
|||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
|
|
||||||
import javax.crypto.Mac;
|
import javax.crypto.Mac;
|
||||||
import javax.crypto.SecretKey;
|
import net.sf.briar.api.crypto.ErasableKey;
|
||||||
|
|
||||||
import net.sf.briar.api.transport.ConnectionWriter;
|
import net.sf.briar.api.transport.ConnectionWriter;
|
||||||
import net.sf.briar.util.ByteUtils;
|
import net.sf.briar.util.ByteUtils;
|
||||||
@@ -31,7 +31,7 @@ implements ConnectionWriter {
|
|||||||
protected long frame = 0L;
|
protected long frame = 0L;
|
||||||
|
|
||||||
ConnectionWriterImpl(ConnectionEncrypter encrypter, Mac mac,
|
ConnectionWriterImpl(ConnectionEncrypter encrypter, Mac mac,
|
||||||
SecretKey macKey) {
|
ErasableKey macKey) {
|
||||||
super(encrypter.getOutputStream());
|
super(encrypter.getOutputStream());
|
||||||
this.encrypter = encrypter;
|
this.encrypter = encrypter;
|
||||||
this.mac = mac;
|
this.mac = mac;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import javax.crypto.Mac;
|
import javax.crypto.Mac;
|
||||||
import javax.crypto.SecretKey;
|
import net.sf.briar.api.crypto.ErasableKey;
|
||||||
|
|
||||||
import net.sf.briar.util.ByteUtils;
|
import net.sf.briar.util.ByteUtils;
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ class PaddedConnectionWriter extends ConnectionWriterImpl {
|
|||||||
private IOException exception = null;
|
private IOException exception = null;
|
||||||
|
|
||||||
PaddedConnectionWriter(ConnectionEncrypter encrypter, Mac mac,
|
PaddedConnectionWriter(ConnectionEncrypter encrypter, Mac mac,
|
||||||
SecretKey macKey) {
|
ErasableKey macKey) {
|
||||||
super(encrypter, mac, macKey);
|
super(encrypter, mac, macKey);
|
||||||
padding = new byte[maxPayloadLength];
|
padding = new byte[maxPayloadLength];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import static org.junit.Assert.assertArrayEquals;
|
|||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.SecretKey;
|
import net.sf.briar.api.crypto.ErasableKey;
|
||||||
import javax.crypto.spec.IvParameterSpec;
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
@@ -26,7 +26,7 @@ public class ConnectionDecrypterImplTest extends TestCase {
|
|||||||
private static final int MAC_LENGTH = 32;
|
private static final int MAC_LENGTH = 32;
|
||||||
|
|
||||||
private final Cipher ivCipher, frameCipher;
|
private final Cipher ivCipher, frameCipher;
|
||||||
private final SecretKey ivKey, frameKey;
|
private final ErasableKey ivKey, frameKey;
|
||||||
private final TransportIndex transportIndex = new TransportIndex(13);
|
private final TransportIndex transportIndex = new TransportIndex(13);
|
||||||
private final long connection = 12345L;
|
private final long connection = 12345L;
|
||||||
|
|
||||||
@@ -36,8 +36,8 @@ public class ConnectionDecrypterImplTest extends TestCase {
|
|||||||
CryptoComponent crypto = i.getInstance(CryptoComponent.class);
|
CryptoComponent crypto = i.getInstance(CryptoComponent.class);
|
||||||
ivCipher = crypto.getIvCipher();
|
ivCipher = crypto.getIvCipher();
|
||||||
frameCipher = crypto.getFrameCipher();
|
frameCipher = crypto.getFrameCipher();
|
||||||
ivKey = crypto.generateSecretKey();
|
ivKey = crypto.generateTestKey();
|
||||||
frameKey = crypto.generateSecretKey();
|
frameKey = crypto.generateTestKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import static org.junit.Assert.assertArrayEquals;
|
|||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.SecretKey;
|
import net.sf.briar.api.crypto.ErasableKey;
|
||||||
import javax.crypto.spec.IvParameterSpec;
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
@@ -24,7 +24,7 @@ public class ConnectionEncrypterImplTest extends TestCase {
|
|||||||
private static final int MAC_LENGTH = 32;
|
private static final int MAC_LENGTH = 32;
|
||||||
|
|
||||||
private final Cipher ivCipher, frameCipher;
|
private final Cipher ivCipher, frameCipher;
|
||||||
private final SecretKey ivKey, frameKey;
|
private final ErasableKey ivKey, frameKey;
|
||||||
private final TransportIndex transportIndex = new TransportIndex(13);
|
private final TransportIndex transportIndex = new TransportIndex(13);
|
||||||
private final long connection = 12345L;
|
private final long connection = 12345L;
|
||||||
|
|
||||||
@@ -34,8 +34,8 @@ public class ConnectionEncrypterImplTest extends TestCase {
|
|||||||
CryptoComponent crypto = i.getInstance(CryptoComponent.class);
|
CryptoComponent crypto = i.getInstance(CryptoComponent.class);
|
||||||
ivCipher = crypto.getIvCipher();
|
ivCipher = crypto.getIvCipher();
|
||||||
frameCipher = crypto.getFrameCipher();
|
frameCipher = crypto.getFrameCipher();
|
||||||
ivKey = crypto.generateSecretKey();
|
ivKey = crypto.generateTestKey();
|
||||||
frameKey = crypto.generateSecretKey();
|
frameKey = crypto.generateTestKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.SecretKey;
|
import net.sf.briar.api.crypto.ErasableKey;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
import net.sf.briar.TestUtils;
|
import net.sf.briar.TestUtils;
|
||||||
@@ -79,7 +79,7 @@ public class ConnectionRecogniserImplTest extends TestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testExpectedIv() throws Exception {
|
public void testExpectedIv() throws Exception {
|
||||||
// Calculate the expected IV for connection number 3
|
// Calculate the expected IV for connection number 3
|
||||||
SecretKey ivKey = crypto.deriveIncomingIvKey(secret);
|
ErasableKey ivKey = crypto.deriveIncomingIvKey(secret);
|
||||||
Cipher ivCipher = crypto.getIvCipher();
|
Cipher ivCipher = crypto.getIvCipher();
|
||||||
ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
|
ivCipher.init(Cipher.ENCRYPT_MODE, ivKey);
|
||||||
byte[] iv = IvEncoder.encodeIv(true, remoteIndex, 3L);
|
byte[] iv = IvEncoder.encodeIv(true, remoteIndex, 3L);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import java.util.Random;
|
|||||||
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.Mac;
|
import javax.crypto.Mac;
|
||||||
import javax.crypto.SecretKey;
|
import net.sf.briar.api.crypto.ErasableKey;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
import net.sf.briar.api.crypto.CryptoComponent;
|
import net.sf.briar.api.crypto.CryptoComponent;
|
||||||
@@ -29,7 +29,7 @@ public class FrameReadWriteTest extends TestCase {
|
|||||||
|
|
||||||
private final CryptoComponent crypto;
|
private final CryptoComponent crypto;
|
||||||
private final Cipher ivCipher, frameCipher;
|
private final Cipher ivCipher, frameCipher;
|
||||||
private final SecretKey ivKey, frameKey, macKey;
|
private final ErasableKey ivKey, frameKey, macKey;
|
||||||
private final Mac mac;
|
private final Mac mac;
|
||||||
private final Random random;
|
private final Random random;
|
||||||
private final byte[] secret = new byte[100];
|
private final byte[] secret = new byte[100];
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package net.sf.briar.transport;
|
|||||||
import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
|
import static net.sf.briar.api.transport.TransportConstants.MAX_FRAME_LENGTH;
|
||||||
|
|
||||||
import javax.crypto.Mac;
|
import javax.crypto.Mac;
|
||||||
import javax.crypto.SecretKey;
|
import net.sf.briar.api.crypto.ErasableKey;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
import net.sf.briar.api.crypto.CryptoComponent;
|
import net.sf.briar.api.crypto.CryptoComponent;
|
||||||
@@ -16,7 +16,7 @@ import com.google.inject.Injector;
|
|||||||
public abstract class TransportTest extends TestCase {
|
public abstract class TransportTest extends TestCase {
|
||||||
|
|
||||||
protected final Mac mac;
|
protected final Mac mac;
|
||||||
protected final SecretKey macKey;
|
protected final ErasableKey macKey;
|
||||||
protected final int headerLength = 4, macLength, maxPayloadLength;
|
protected final int headerLength = 4, macLength, maxPayloadLength;
|
||||||
|
|
||||||
public TransportTest() throws Exception {
|
public TransportTest() throws Exception {
|
||||||
@@ -24,7 +24,7 @@ public abstract class TransportTest extends TestCase {
|
|||||||
Injector i = Guice.createInjector(new CryptoModule());
|
Injector i = Guice.createInjector(new CryptoModule());
|
||||||
CryptoComponent crypto = i.getInstance(CryptoComponent.class);
|
CryptoComponent crypto = i.getInstance(CryptoComponent.class);
|
||||||
mac = crypto.getMac();
|
mac = crypto.getMac();
|
||||||
macKey = crypto.generateSecretKey();
|
macKey = crypto.generateTestKey();
|
||||||
macLength = mac.getMacLength();
|
macLength = mac.getMacLength();
|
||||||
maxPayloadLength = MAX_FRAME_LENGTH - headerLength - macLength;
|
maxPayloadLength = MAX_FRAME_LENGTH - headerLength - macLength;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user