Removed all uses of JCE so we can use full-strength crypto on all JVMs.

This commit is contained in:
akwizgran
2013-06-17 16:22:02 +01:00
parent 8a039f0747
commit 3e0c16b59a
53 changed files with 487 additions and 693 deletions

View File

@@ -1,13 +1,11 @@
package net.sf.briar.crypto;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.GeneralSecurityException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import net.sf.briar.api.crypto.AuthenticatedCipher;
import net.sf.briar.api.crypto.SecretKey;
import org.spongycastle.crypto.DataLengthException;
import org.spongycastle.crypto.InvalidCipherTextException;
@@ -26,8 +24,7 @@ class AuthenticatedCipherImpl implements AuthenticatedCipher {
}
public int doFinal(byte[] input, int inputOff, int len, byte[] output,
int outputOff) throws IllegalBlockSizeException,
BadPaddingException {
int outputOff) throws GeneralSecurityException {
int processed = 0;
if(len != 0) {
processed = cipher.processBytes(input, inputOff, len, output,
@@ -36,14 +33,14 @@ class AuthenticatedCipherImpl implements AuthenticatedCipher {
try {
return processed + cipher.doFinal(output, outputOff + processed);
} catch(DataLengthException e) {
throw new IllegalBlockSizeException(e.getMessage());
throw new GeneralSecurityException(e.getMessage());
} catch(InvalidCipherTextException e) {
throw new BadPaddingException(e.getMessage());
throw new GeneralSecurityException(e.getMessage());
}
}
public void init(int opmode, Key key, byte[] iv, byte[] aad)
throws InvalidKeyException {
public void init(int opmode, SecretKey key, byte[] iv, byte[] aad)
throws GeneralSecurityException {
KeyParameter k = new KeyParameter(key.getEncoded());
AEADParameters params = new AEADParameters(k, macLength * 8, iv, aad);
try {
@@ -59,8 +56,8 @@ class AuthenticatedCipherImpl implements AuthenticatedCipher {
default:
throw new IllegalArgumentException();
}
} catch(Exception e) {
throw new InvalidKeyException(e.getMessage());
} catch(IllegalArgumentException e) {
throw new GeneralSecurityException(e.getMessage());
}
}

View File

@@ -1,72 +1,54 @@
package net.sf.briar.crypto;
import static java.util.logging.Level.INFO;
import static javax.crypto.Cipher.DECRYPT_MODE;
import static javax.crypto.Cipher.ENCRYPT_MODE;
import static net.sf.briar.api.invitation.InvitationConstants.CODE_BITS;
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
import static net.sf.briar.crypto.P384Constants.P_384_PARAMS;
import static net.sf.briar.crypto.P384Constants.P_384_Q;
import static net.sf.briar.util.ByteUtils.MAX_32_BIT_UNSIGNED;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.Signature;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECField;
import java.security.spec.ECFieldFp;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.EllipticCurve;
import java.util.Arrays;
import java.util.logging.Logger;
import javax.crypto.KeyAgreement;
import net.sf.briar.api.crypto.AuthenticatedCipher;
import net.sf.briar.api.crypto.CryptoComponent;
import net.sf.briar.api.crypto.ErasableKey;
import net.sf.briar.api.crypto.KeyPair;
import net.sf.briar.api.crypto.KeyParser;
import net.sf.briar.api.crypto.MessageDigest;
import net.sf.briar.api.crypto.PrivateKey;
import net.sf.briar.api.crypto.PseudoRandom;
import net.sf.briar.api.crypto.PublicKey;
import net.sf.briar.api.crypto.SecretKey;
import net.sf.briar.api.crypto.Signature;
import net.sf.briar.util.ByteUtils;
import org.spongycastle.crypto.AsymmetricCipherKeyPair;
import org.spongycastle.crypto.BlockCipher;
import org.spongycastle.crypto.CipherParameters;
import org.spongycastle.crypto.agreement.ECDHCBasicAgreement;
import org.spongycastle.crypto.digests.SHA384Digest;
import org.spongycastle.crypto.engines.AESFastEngine;
import org.spongycastle.crypto.generators.ECKeyPairGenerator;
import org.spongycastle.crypto.generators.PKCS5S2ParametersGenerator;
import org.spongycastle.crypto.modes.AEADBlockCipher;
import org.spongycastle.crypto.modes.GCMBlockCipher;
import org.spongycastle.crypto.params.ECKeyGenerationParameters;
import org.spongycastle.crypto.params.ECPrivateKeyParameters;
import org.spongycastle.crypto.params.ECPublicKeyParameters;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.jcajce.provider.asymmetric.ec.KeyPairGeneratorSpi;
import org.spongycastle.jcajce.provider.digest.SHA384;
import org.spongycastle.jce.provider.BouncyCastleProvider;
import org.spongycastle.util.Strings;
class CryptoComponentImpl implements CryptoComponent {
private static final Logger LOG =
Logger.getLogger(CryptoComponentImpl.class.getName());
private static final String PROVIDER = "SC"; // Spongy Castle
private static final String CIPHER_ALGO = "AES";
private static final int CIPHER_BLOCK_BYTES = 16; // 128 bits
private static final int CIPHER_KEY_BYTES = 32; // 256 bits
private static final String AGREEMENT_ALGO = "ECDHC";
private static final String AGREEMENT_KEY_PAIR_ALGO = "ECDH";
private static final int AGREEMENT_KEY_PAIR_BITS = 384;
private static final String SIGNATURE_ALGO = "ECDSA";
private static final String SIGNATURE_KEY_PAIR_ALGO = "ECDSA";
private static final int SIGNATURE_KEY_PAIR_BITS = 384;
private static final int GCM_MAC_BYTES = 16; // 128 bits
private static final int MAC_BYTES = 16; // 128 bits
private static final int STORAGE_IV_BYTES = 16; // 128 bits
private static final int PBKDF_SALT_BYTES = 16; // 128 bits
private static final int PBKDF_ITERATIONS = 1000;
@@ -93,83 +75,33 @@ class CryptoComponentImpl implements CryptoComponent {
// Blank secret for argument validation
private static final byte[] BLANK_SECRET = new byte[CIPHER_KEY_BYTES];
// Parameters for NIST elliptic curve P-384 - see "Suite B Implementer's
// Guide to NIST SP 800-56A", section A.2
private static final BigInteger P_384_Q = new BigInteger("FFFFFFFF" +
"FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" +
"FFFFFFFF" + "FFFFFFFE" + "FFFFFFFF" + "00000000" + "00000000" +
"FFFFFFFF", 16);
private static final BigInteger P_384_A = new BigInteger("FFFFFFFF" +
"FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" +
"FFFFFFFF" + "FFFFFFFE" + "FFFFFFFF" + "00000000" + "00000000" +
"FFFFFFFC", 16);
private static final BigInteger P_384_B = new BigInteger("B3312FA7" +
"E23EE7E4" + "988E056B" + "E3F82D19" + "181D9C6E" + "FE814112" +
"0314088F" + "5013875A" + "C656398D" + "8A2ED19D" + "2A85C8ED" +
"D3EC2AEF", 16);
private static final BigInteger P_384_G_X = new BigInteger("AA87CA22" +
"BE8B0537" + "8EB1C71E" + "F320AD74" + "6E1D3B62" + "8BA79B98" +
"59F741E0" + "82542A38" + "5502F25D" + "BF55296C" + "3A545E38" +
"72760AB7", 16);
private static final BigInteger P_384_G_Y = new BigInteger("3617DE4A" +
"96262C6F" + "5D9E98BF" + "9292DC29" + "F8F41DBD" + "289A147C" +
"E9DA3113" + "B5F0B8C0" + "0A60B1CE" + "1D7E819D" + "7A431D7C" +
"90EA0E5F", 16);
private static final BigInteger P_384_N = new BigInteger("FFFFFFFF" +
"FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" +
"C7634D81" + "F4372DDF" + "581A0DB2" + "48B0A77A" + "ECEC196A" +
"CCC52973", 16);
private static final int P_384_H = 1;
// Static parameter objects derived from the above parameters
private static final ECField P_384_FIELD = new ECFieldFp(P_384_Q);
private static final EllipticCurve P_384_CURVE =
new EllipticCurve(P_384_FIELD, P_384_A, P_384_B);
private static final ECPoint P_384_G = new ECPoint(P_384_G_X, P_384_G_Y);
private static final ECParameterSpec P_384_PARAMS =
new ECParameterSpec(P_384_CURVE, P_384_G, P_384_N, P_384_H);
private final KeyParser agreementKeyParser, signatureKeyParser;
private final KeyPairGenerator agreementKeyPairGenerator;
private final KeyPairGenerator signatureKeyPairGenerator;
private final SecureRandom secureRandom;
private final ECKeyPairGenerator agreementKeyPairGenerator;
private final ECKeyPairGenerator signatureKeyPairGenerator;
CryptoComponentImpl() {
Security.addProvider(new BouncyCastleProvider());
try {
KeyFactory agreementKeyFactory = KeyFactory.getInstance(
AGREEMENT_KEY_PAIR_ALGO, PROVIDER);
if(LOG.isLoggable(INFO)) {
LOG.info("Agreement KeyFactory: "
+ agreementKeyFactory.getClass().getName());
}
agreementKeyParser = new Sec1KeyParser(agreementKeyFactory,
P_384_PARAMS, P_384_Q, AGREEMENT_KEY_PAIR_BITS);
KeyFactory signatureKeyFactory = KeyFactory.getInstance(
SIGNATURE_KEY_PAIR_ALGO, PROVIDER);
if(LOG.isLoggable(INFO)) {
LOG.info("Signature KeyFactory: "
+ signatureKeyFactory.getClass().getName());
}
signatureKeyParser = new Sec1KeyParser(signatureKeyFactory,
P_384_PARAMS, P_384_Q, SIGNATURE_KEY_PAIR_BITS);
agreementKeyPairGenerator = new KeyPairGeneratorSpi.ECDH();
agreementKeyPairGenerator.initialize(AGREEMENT_KEY_PAIR_BITS);
signatureKeyPairGenerator = new KeyPairGeneratorSpi.ECDSA();
signatureKeyPairGenerator.initialize(SIGNATURE_KEY_PAIR_BITS);
} catch(GeneralSecurityException e) {
throw new RuntimeException(e);
}
agreementKeyParser = new Sec1KeyParser(P_384_PARAMS, P_384_Q,
AGREEMENT_KEY_PAIR_BITS);
signatureKeyParser = new Sec1KeyParser(P_384_PARAMS, P_384_Q,
SIGNATURE_KEY_PAIR_BITS);
secureRandom = new SecureRandom();
ECKeyGenerationParameters params = new ECKeyGenerationParameters(
P_384_PARAMS, secureRandom);
agreementKeyPairGenerator = new ECKeyPairGenerator();
agreementKeyPairGenerator.init(params);
signatureKeyPairGenerator = new ECKeyPairGenerator();
signatureKeyPairGenerator.init(params);
}
public ErasableKey generateSecretKey() {
public SecretKey generateSecretKey() {
byte[] b = new byte[CIPHER_KEY_BYTES];
secureRandom.nextBytes(b);
return new ErasableKeyImpl(b, CIPHER_ALGO);
return new SecretKeyImpl(b);
}
public MessageDigest getMessageDigest() {
return new DoubleDigest(new SHA384.Digest());
return new DoubleDigest(new SHA384Digest());
}
public PseudoRandom getPseudoRandom(int seed1, int seed2) {
@@ -181,25 +113,21 @@ class CryptoComponentImpl implements CryptoComponent {
}
public Signature getSignature() {
try {
Signature signature = Signature.getInstance(SIGNATURE_ALGO,
PROVIDER);
if(LOG.isLoggable(INFO))
LOG.info("Signature: " + signature.getClass().getName());
return signature;
} catch(GeneralSecurityException e) {
throw new RuntimeException(e);
}
return new SignatureImpl(secureRandom);
}
public KeyPair generateAgreementKeyPair() {
KeyPair keyPair = agreementKeyPairGenerator.generateKeyPair();
// Check that the key pair uses NIST curve P-384
ECPublicKey publicKey = checkP384Params(keyPair.getPublic());
AsymmetricCipherKeyPair keyPair =
agreementKeyPairGenerator.generateKeyPair();
// Return a wrapper that uses the SEC 1 encoding
publicKey = new Sec1PublicKey(publicKey, AGREEMENT_KEY_PAIR_BITS);
ECPrivateKey privateKey = (ECPrivateKey) keyPair.getPrivate();
privateKey = new Sec1PrivateKey(privateKey, AGREEMENT_KEY_PAIR_BITS);
ECPublicKeyParameters ecPublicKey =
(ECPublicKeyParameters) keyPair.getPublic();
PublicKey publicKey = new Sec1PublicKey(ecPublicKey,
AGREEMENT_KEY_PAIR_BITS);
ECPrivateKeyParameters ecPrivateKey =
(ECPrivateKeyParameters) keyPair.getPrivate();
PrivateKey privateKey = new Sec1PrivateKey(ecPrivateKey,
AGREEMENT_KEY_PAIR_BITS);
return new KeyPair(publicKey, privateKey);
}
@@ -208,13 +136,17 @@ class CryptoComponentImpl implements CryptoComponent {
}
public KeyPair generateSignatureKeyPair() {
KeyPair keyPair = signatureKeyPairGenerator.generateKeyPair();
// Check that the key pair uses NIST curve P-384
ECPublicKey publicKey = checkP384Params(keyPair.getPublic());
AsymmetricCipherKeyPair keyPair =
signatureKeyPairGenerator.generateKeyPair();
// Return a wrapper that uses the SEC 1 encoding
publicKey = new Sec1PublicKey(publicKey, SIGNATURE_KEY_PAIR_BITS);
ECPrivateKey privateKey = (ECPrivateKey) keyPair.getPrivate();
privateKey = new Sec1PrivateKey(privateKey, SIGNATURE_KEY_PAIR_BITS);
ECPublicKeyParameters ecPublicKey =
(ECPublicKeyParameters) keyPair.getPublic();
PublicKey publicKey = new Sec1PublicKey(ecPublicKey,
SIGNATURE_KEY_PAIR_BITS);
ECPrivateKeyParameters ecPrivateKey =
(ECPrivateKeyParameters) keyPair.getPrivate();
PrivateKey privateKey = new Sec1PrivateKey(ecPrivateKey,
SIGNATURE_KEY_PAIR_BITS);
return new KeyPair(publicKey, privateKey);
}
@@ -282,13 +214,16 @@ class CryptoComponentImpl implements CryptoComponent {
// Package access for testing
byte[] deriveSharedSecret(PrivateKey priv, PublicKey pub)
throws GeneralSecurityException {
KeyAgreement keyAgreement = KeyAgreement.getInstance(AGREEMENT_ALGO,
PROVIDER);
if(LOG.isLoggable(INFO))
LOG.info("KeyAgreement: " + keyAgreement.getClass().getName());
keyAgreement.init(priv);
keyAgreement.doPhase(pub, true);
return keyAgreement.generateSecret();
if(!(priv instanceof Sec1PrivateKey))
throw new IllegalArgumentException();
if(!(pub instanceof Sec1PublicKey))
throw new IllegalArgumentException();
ECPrivateKeyParameters ecPriv = ((Sec1PrivateKey) priv).getKey();
ECPublicKeyParameters ecPub = ((Sec1PublicKey) pub).getKey();
ECDHCBasicAgreement agreement = new ECDHCBasicAgreement();
agreement.init(ecPriv);
// FIXME: Should we use another format for the shared secret?
return agreement.calculateAgreement(ecPub).toByteArray();
}
public byte[] deriveInitialSecret(byte[] secret, int transportIndex) {
@@ -310,7 +245,7 @@ class CryptoComponentImpl implements CryptoComponent {
return counterModeKdf(secret, ROTATE, period);
}
public ErasableKey deriveTagKey(byte[] secret, boolean alice) {
public SecretKey deriveTagKey(byte[] secret, boolean alice) {
if(secret.length != CIPHER_KEY_BYTES)
throw new IllegalArgumentException();
if(Arrays.equals(secret, BLANK_SECRET))
@@ -319,7 +254,7 @@ class CryptoComponentImpl implements CryptoComponent {
else return deriveKey(secret, B_TAG, 0);
}
public ErasableKey deriveFrameKey(byte[] secret, long connection,
public SecretKey deriveFrameKey(byte[] secret, long connection,
boolean alice, boolean initiator) {
if(secret.length != CIPHER_KEY_BYTES)
throw new IllegalArgumentException();
@@ -336,21 +271,21 @@ class CryptoComponentImpl implements CryptoComponent {
}
}
private ErasableKey deriveKey(byte[] secret, byte[] label, long context) {
private SecretKey deriveKey(byte[] secret, byte[] label, long context) {
if(secret.length != CIPHER_KEY_BYTES)
throw new IllegalArgumentException();
if(Arrays.equals(secret, BLANK_SECRET))
throw new IllegalArgumentException();
byte[] key = counterModeKdf(secret, label, context);
return new ErasableKeyImpl(key, CIPHER_ALGO);
return new SecretKeyImpl(key);
}
public AuthenticatedCipher getFrameCipher() {
AEADBlockCipher cipher = new GCMBlockCipher(new AESFastEngine());
return new AuthenticatedCipherImpl(cipher, GCM_MAC_BYTES);
return new AuthenticatedCipherImpl(cipher, MAC_BYTES);
}
public void encodeTag(byte[] tag, ErasableKey tagKey, long connection) {
public void encodeTag(byte[] tag, SecretKey tagKey, long connection) {
if(tag.length < TAG_LENGTH) throw new IllegalArgumentException();
if(connection < 0 || connection > MAX_32_BIT_UNSIGNED)
throw new IllegalArgumentException();
@@ -367,12 +302,12 @@ class CryptoComponentImpl implements CryptoComponent {
secureRandom.nextBytes(salt);
// Derive the key from the password
byte[] keyBytes = pbkdf2(password, salt);
ErasableKey key = new ErasableKeyImpl(keyBytes, CIPHER_ALGO);
SecretKey key = new SecretKeyImpl(keyBytes);
// Generate a random IV
byte[] iv = new byte[STORAGE_IV_BYTES];
secureRandom.nextBytes(iv);
// The output contains the salt, IV, ciphertext and MAC
int outputLen = salt.length + iv.length + input.length + GCM_MAC_BYTES;
int outputLen = salt.length + iv.length + input.length + MAC_BYTES;
byte[] output = new byte[outputLen];
System.arraycopy(salt, 0, output, 0, salt.length);
System.arraycopy(iv, 0, output, salt.length, iv.length);
@@ -380,7 +315,7 @@ class CryptoComponentImpl implements CryptoComponent {
try {
AEADBlockCipher c = new GCMBlockCipher(new AESFastEngine());
AuthenticatedCipher cipher = new AuthenticatedCipherImpl(c,
GCM_MAC_BYTES);
MAC_BYTES);
cipher.init(ENCRYPT_MODE, key, iv, null);
int outputOff = salt.length + iv.length;
cipher.doFinal(input, 0, input.length, output, outputOff);
@@ -394,7 +329,7 @@ class CryptoComponentImpl implements CryptoComponent {
public byte[] decryptWithPassword(byte[] input, char[] password) {
// The input contains the salt, IV, ciphertext and MAC
if(input.length < PBKDF_SALT_BYTES + STORAGE_IV_BYTES + GCM_MAC_BYTES)
if(input.length < PBKDF_SALT_BYTES + STORAGE_IV_BYTES + MAC_BYTES)
return null; // Invalid
byte[] salt = new byte[PBKDF_SALT_BYTES];
System.arraycopy(input, 0, salt, 0, salt.length);
@@ -402,12 +337,12 @@ class CryptoComponentImpl implements CryptoComponent {
System.arraycopy(input, salt.length, iv, 0, iv.length);
// Derive the key from the password
byte[] keyBytes = pbkdf2(password, salt);
ErasableKey key = new ErasableKeyImpl(keyBytes, CIPHER_ALGO);
SecretKey key = new SecretKeyImpl(keyBytes);
// Initialise the cipher
AuthenticatedCipher cipher;
try {
AEADBlockCipher c = new GCMBlockCipher(new AESFastEngine());
cipher = new AuthenticatedCipherImpl(c, GCM_MAC_BYTES);
cipher = new AuthenticatedCipherImpl(c, MAC_BYTES);
cipher.init(DECRYPT_MODE, key, iv, null);
} catch(GeneralSecurityException e) {
key.erase();
@@ -417,7 +352,7 @@ class CryptoComponentImpl implements CryptoComponent {
try {
int inputOff = salt.length + iv.length;
int inputLen = input.length - salt.length - iv.length;
byte[] output = new byte[inputLen - GCM_MAC_BYTES];
byte[] output = new byte[inputLen - MAC_BYTES];
cipher.doFinal(input, inputOff, inputLen, output, 0);
return output;
} catch(GeneralSecurityException e) {
@@ -427,23 +362,6 @@ class CryptoComponentImpl implements CryptoComponent {
}
}
private ECPublicKey checkP384Params(PublicKey publicKey) {
if(!(publicKey instanceof ECPublicKey)) throw new RuntimeException();
ECPublicKey ecPublicKey = (ECPublicKey) publicKey;
ECParameterSpec params = ecPublicKey.getParams();
EllipticCurve curve = params.getCurve();
ECField field = curve.getField();
if(!(field instanceof ECFieldFp)) throw new RuntimeException();
BigInteger q = ((ECFieldFp) field).getP();
if(!q.equals(P_384_Q)) throw new RuntimeException();
if(!curve.getA().equals(P_384_A)) throw new RuntimeException();
if(!curve.getB().equals(P_384_B)) throw new RuntimeException();
if(!params.getGenerator().equals(P_384_G)) throw new RuntimeException();
if(!params.getOrder().equals(P_384_N)) throw new RuntimeException();
if(!(params.getCofactor() == P_384_H)) throw new RuntimeException();
return ecPublicKey;
}
// Key derivation function based on a hash function - see NIST SP 800-56A,
// section 5.8
private byte[] concatenationKdf(byte[] rawSecret, byte[] label,
@@ -499,8 +417,6 @@ class CryptoComponentImpl implements CryptoComponent {
// Password-based key derivation function - see PKCS#5 v2.1, section 5.2
private byte[] pbkdf2(char[] password, byte[] salt) {
// This code is specific to Spongy Castle because the password-based
// KDF exposed through the JCE interface is PKCS#12
byte[] utf8 = toUtf8ByteArray(password);
PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator();
gen.init(utf8, salt, PBKDF_ITERATIONS);

View File

@@ -2,6 +2,8 @@ package net.sf.briar.crypto;
import net.sf.briar.api.crypto.MessageDigest;
import org.spongycastle.crypto.Digest;
/**
* A message digest that prevents length extension attacks - see Ferguson and
* Schneier, <i>Practical Cryptography</i>, chapter 6.
@@ -13,20 +15,22 @@ import net.sf.briar.api.crypto.MessageDigest;
*/
class DoubleDigest implements MessageDigest {
private final java.security.MessageDigest delegate;
private final Digest delegate;
DoubleDigest(java.security.MessageDigest delegate) {
DoubleDigest(Digest delegate) {
this.delegate = delegate;
}
public byte[] digest() {
byte[] digest = delegate.digest(); // h(m)
delegate.update(digest);
return delegate.digest(); // h(h(m))
byte[] digest = new byte[delegate.getDigestSize()];
delegate.doFinal(digest, 0); // h(m)
delegate.update(digest, 0, digest.length);
delegate.doFinal(digest, 0); // h(h(m))
return digest;
}
public byte[] digest(byte[] input) {
delegate.update(input);
delegate.update(input, 0, input.length);
return digest();
}
@@ -38,7 +42,7 @@ class DoubleDigest implements MessageDigest {
}
public int getDigestLength() {
return delegate.getDigestLength();
return delegate.getDigestSize();
}
public void reset() {
@@ -50,7 +54,7 @@ class DoubleDigest implements MessageDigest {
}
public void update(byte[] input) {
delegate.update(input);
delegate.update(input, 0, input.length);
}
public void update(byte[] input, int offset, int len) {

View File

@@ -1,42 +0,0 @@
package net.sf.briar.crypto;
import net.sf.briar.api.crypto.ErasableKey;
import net.sf.briar.util.ByteUtils;
class ErasableKeyImpl implements ErasableKey {
private static final long serialVersionUID = -4438380720846443120L;
private final byte[] key;
private final String algorithm;
private boolean erased = false; // Locking: this
ErasableKeyImpl(byte[] key, String algorithm) {
this.key = key;
this.algorithm = algorithm;
}
public String getAlgorithm() {
return algorithm;
}
public synchronized byte[] getEncoded() {
if(erased) throw new IllegalStateException();
return key;
}
public String getFormat() {
return "RAW";
}
public ErasableKey copy() {
return new ErasableKeyImpl(key.clone(), algorithm);
}
public synchronized void erase() {
if(erased) throw new IllegalStateException();
ByteUtils.erase(key);
erased = true;
}
}

View File

@@ -0,0 +1,41 @@
package net.sf.briar.crypto;
import java.math.BigInteger;
import org.spongycastle.crypto.params.ECDomainParameters;
import org.spongycastle.math.ec.ECCurve;
import org.spongycastle.math.ec.ECFieldElement;
import org.spongycastle.math.ec.ECPoint;
interface P384Constants {
// Parameters for NIST elliptic curve P-384 - see "Suite B Implementer's
// Guide to NIST SP 800-56A", section A.2
BigInteger P_384_Q = new BigInteger("FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" +
"FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFE" +
"FFFFFFFF" + "00000000" + "00000000" + "FFFFFFFF", 16);
BigInteger P_384_A = new BigInteger("FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" +
"FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "FFFFFFFE" +
"FFFFFFFF" + "00000000" + "00000000" + "FFFFFFFC", 16);
BigInteger P_384_B = new BigInteger("B3312FA7" + "E23EE7E4" + "988E056B" +
"E3F82D19" + "181D9C6E" + "FE814112" + "0314088F" + "5013875A" +
"C656398D" + "8A2ED19D" + "2A85C8ED" + "D3EC2AEF", 16);
BigInteger P_384_G_X = new BigInteger("AA87CA22" + "BE8B0537" + "8EB1C71E" +
"F320AD74" + "6E1D3B62" + "8BA79B98" + "59F741E0" + "82542A38" +
"5502F25D" + "BF55296C" + "3A545E38" + "72760AB7", 16);
BigInteger P_384_G_Y = new BigInteger("3617DE4A" + "96262C6F" + "5D9E98BF" +
"9292DC29" + "F8F41DBD" + "289A147C" + "E9DA3113" + "B5F0B8C0" +
"0A60B1CE" + "1D7E819D" + "7A431D7C" + "90EA0E5F", 16);
BigInteger P_384_N = new BigInteger("FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" +
"FFFFFFFF" + "FFFFFFFF" + "FFFFFFFF" + "C7634D81" + "F4372DDF" +
"581A0DB2" + "48B0A77A" + "ECEC196A" + "CCC52973", 16);
BigInteger P_384_H = BigInteger.ONE;
// Static parameter objects derived from the above parameters
ECCurve P_384_CURVE = new ECCurve.Fp(P_384_Q, P_384_A, P_384_B);
ECPoint P_384_G = new ECPoint.Fp(P_384_CURVE,
new ECFieldElement.Fp(P_384_Q, P_384_G_X),
new ECFieldElement.Fp(P_384_Q, P_384_G_Y));
ECDomainParameters P_384_PARAMS = new ECDomainParameters(P_384_CURVE,
P_384_G, P_384_N, P_384_H);
}

View File

@@ -1,18 +1,17 @@
package net.sf.briar.crypto;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.ECPrivateKeySpec;
import java.security.spec.ECPublicKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.GeneralSecurityException;
import net.sf.briar.api.crypto.KeyParser;
import net.sf.briar.api.crypto.PrivateKey;
import net.sf.briar.api.crypto.PublicKey;
import org.spongycastle.crypto.params.ECDomainParameters;
import org.spongycastle.crypto.params.ECPrivateKeyParameters;
import org.spongycastle.crypto.params.ECPublicKeyParameters;
import org.spongycastle.math.ec.ECFieldElement;
import org.spongycastle.math.ec.ECPoint;
/**
* A key parser that uses the encoding defined in "SEC 1: Elliptic Curve
@@ -21,14 +20,11 @@ import net.sf.briar.api.crypto.KeyParser;
*/
class Sec1KeyParser implements KeyParser {
private final KeyFactory keyFactory;
private final ECParameterSpec params;
private final ECDomainParameters params;
private final BigInteger modulus;
private final int keyBits, bytesPerInt, publicKeyBytes, privateKeyBytes;
Sec1KeyParser(KeyFactory keyFactory, ECParameterSpec params,
BigInteger modulus, int keyBits) {
this.keyFactory = keyFactory;
Sec1KeyParser(ECDomainParameters params, BigInteger modulus, int keyBits) {
this.params = params;
this.modulus = modulus;
this.keyBits = keyBits;
@@ -38,43 +34,48 @@ class Sec1KeyParser implements KeyParser {
}
public PublicKey parsePublicKey(byte[] encodedKey)
throws InvalidKeySpecException {
throws GeneralSecurityException {
if(encodedKey.length != publicKeyBytes)
throw new InvalidKeySpecException();
throw new GeneralSecurityException();
// The first byte must be 0x04
if(encodedKey[0] != 4) throw new InvalidKeySpecException();
if(encodedKey[0] != 4) throw new GeneralSecurityException();
// The x co-ordinate must be >= 0 and < q
byte[] xBytes = new byte[bytesPerInt];
System.arraycopy(encodedKey, 1, xBytes, 0, bytesPerInt);
BigInteger x = new BigInteger(1, xBytes); // Positive signum
if(x.compareTo(modulus) >= 0) throw new InvalidKeySpecException();
if(x.compareTo(modulus) >= 0) throw new GeneralSecurityException();
// The y co-ordinate must be >= 0 and < q
byte[] yBytes = new byte[bytesPerInt];
System.arraycopy(encodedKey, bytesPerInt + 1, yBytes, 0, bytesPerInt);
BigInteger y = new BigInteger(1, yBytes); // Positive signum
if(y.compareTo(modulus) >= 0) throw new InvalidKeySpecException();
if(y.compareTo(modulus) >= 0) throw new GeneralSecurityException();
// Verify that y^2 == x^3 + ax + b (mod q)
BigInteger a = params.getCurve().getA(), b = params.getCurve().getB();
BigInteger a = params.getCurve().getA().toBigInteger();
BigInteger b = params.getCurve().getB().toBigInteger();
BigInteger lhs = y.multiply(y).mod(modulus);
BigInteger rhs = x.multiply(x).add(a).multiply(x).add(b).mod(modulus);
if(!lhs.equals(rhs)) throw new InvalidKeySpecException();
// FIXME: Verify that n times the point (x, y) = the point at infinity
if(!lhs.equals(rhs)) throw new GeneralSecurityException();
// Verify that the point (x, y) times n = the point at infinity
ECFieldElement elementX = new ECFieldElement.Fp(modulus, x);
ECFieldElement elementY = new ECFieldElement.Fp(modulus, y);
ECPoint pub = new ECPoint.Fp(params.getCurve(), elementX, elementY);
if(!pub.multiply(params.getN()).isInfinity())
throw new GeneralSecurityException();
// Construct a public key from the point (x, y) and the params
ECPoint pub = new ECPoint(x, y);
ECPublicKeySpec keySpec = new ECPublicKeySpec(pub, params);
ECPublicKey k = (ECPublicKey) keyFactory.generatePublic(keySpec);
ECPublicKeyParameters k = new ECPublicKeyParameters(pub, params);
return new Sec1PublicKey(k, keyBits);
}
public PrivateKey parsePrivateKey(byte[] encodedKey)
throws InvalidKeySpecException {
throws GeneralSecurityException {
if(encodedKey.length != privateKeyBytes)
throw new InvalidKeySpecException();
BigInteger s = new BigInteger(1, encodedKey); // Positive signum
if(s.compareTo(params.getOrder()) >= 0)
throw new InvalidKeySpecException();
ECPrivateKeySpec keySpec = new ECPrivateKeySpec(s, params);
ECPrivateKey k = (ECPrivateKey) keyFactory.generatePrivate(keySpec);
throw new GeneralSecurityException();
BigInteger d = new BigInteger(1, encodedKey); // Positive signum
// Verify that the private value is < n
if(d.compareTo(params.getN()) >= 0)
throw new GeneralSecurityException();
// Construct a private key from the private value and the params
ECPrivateKeyParameters k = new ECPrivateKeyParameters(d, params);
return new Sec1PrivateKey(k, keyBits);
}
}

View File

@@ -1,57 +1,32 @@
package net.sf.briar.crypto;
import java.math.BigInteger;
import java.security.interfaces.ECPrivateKey;
import java.security.spec.ECParameterSpec;
class Sec1PrivateKey implements ECPrivateKey,
org.spongycastle.jce.interfaces.ECPrivateKey {
import net.sf.briar.api.crypto.PrivateKey;
private static final long serialVersionUID = -493100835871466670L;
import org.spongycastle.crypto.params.ECPrivateKeyParameters;
private final ECPrivateKey key;
class Sec1PrivateKey implements PrivateKey {
private final ECPrivateKeyParameters key;
private final int privateKeyBytes;
Sec1PrivateKey(ECPrivateKey key, int keyBits) {
// Spongy Castle only accepts instances of its own interface, so we
// have to wrap an instance of that interface and delegate to it
if(!(key instanceof org.spongycastle.jce.interfaces.ECPrivateKey))
throw new IllegalArgumentException();
Sec1PrivateKey(ECPrivateKeyParameters key, int keyBits) {
this.key = key;
privateKeyBytes = (int) Math.ceil(keyBits / 8.0);
}
public String getAlgorithm() {
return key.getAlgorithm();
}
public byte[] getEncoded() {
byte[] encodedKey = new byte[privateKeyBytes];
BigInteger s = key.getS();
BigInteger d = key.getD();
// Copy up to privateKeyBytes bytes into exactly privateKeyBytes bytes
byte[] sBytes = s.toByteArray();
for(int i = 0; i < sBytes.length && i < privateKeyBytes; i++)
encodedKey[privateKeyBytes - 1 - i] = sBytes[sBytes.length - 1 - i];
byte[] dBytes = d.toByteArray();
for(int i = 0; i < dBytes.length && i < privateKeyBytes; i++)
encodedKey[privateKeyBytes - 1 - i] = dBytes[dBytes.length - 1 - i];
return encodedKey;
}
public String getFormat() {
return "SEC1";
}
public ECParameterSpec getParams() {
return key.getParams();
}
public BigInteger getS() {
return key.getS();
}
public org.spongycastle.jce.spec.ECParameterSpec getParameters() {
return ((org.spongycastle.jce.interfaces.ECPrivateKey) key).getParameters();
}
public BigInteger getD() {
return ((org.spongycastle.jce.interfaces.ECPrivateKey) key).getD();
ECPrivateKeyParameters getKey() {
return key;
}
}

View File

@@ -1,42 +1,32 @@
package net.sf.briar.crypto;
import java.math.BigInteger;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import net.sf.briar.api.crypto.PublicKey;
import org.spongycastle.crypto.params.ECPublicKeyParameters;
/**
* An elliptic curve public key that uses the encoding defined in "SEC 1:
* Elliptic Curve Cryptography", section 2.3 (Certicom Corporation, May 2009).
* Point compression is not used.
*/
class Sec1PublicKey implements ECPublicKey,
org.spongycastle.jce.interfaces.ECPublicKey {
class Sec1PublicKey implements PublicKey {
private static final long serialVersionUID = -2722797033851423987L;
private final ECPublicKey key;
private final ECPublicKeyParameters key;
private final int bytesPerInt, publicKeyBytes;
Sec1PublicKey(ECPublicKey key, int keyBits) {
// Spongy Castle only accepts instances of its own interface, so we
// have to wrap an instance of that interface and delegate to it
if(!(key instanceof org.spongycastle.jce.interfaces.ECPublicKey))
throw new IllegalArgumentException();
Sec1PublicKey(ECPublicKeyParameters key, int keyBits) {
this.key = key;
bytesPerInt = (int) Math.ceil(keyBits / 8.0);
publicKeyBytes = 1 + 2 * bytesPerInt;
}
public String getAlgorithm() {
return key.getAlgorithm();
}
public byte[] getEncoded() {
byte[] encodedKey = new byte[publicKeyBytes];
encodedKey[0] = 4;
BigInteger x = key.getW().getAffineX();
BigInteger y = key.getW().getAffineY();
BigInteger x = key.getQ().getX().toBigInteger();
BigInteger y = key.getQ().getY().toBigInteger();
// Copy up to bytesPerInt bytes into exactly bytesPerInt bytes
byte[] xBytes = x.toByteArray();
for(int i = 0; i < xBytes.length && i < bytesPerInt; i++)
@@ -47,23 +37,7 @@ org.spongycastle.jce.interfaces.ECPublicKey {
return encodedKey;
}
public String getFormat() {
return "SEC1";
}
public ECParameterSpec getParams() {
return key.getParams();
}
public ECPoint getW() {
return key.getW();
}
public org.spongycastle.jce.spec.ECParameterSpec getParameters() {
return ((org.spongycastle.jce.interfaces.ECPublicKey) key).getParameters();
}
public org.spongycastle.math.ec.ECPoint getQ() {
return ((org.spongycastle.jce.interfaces.ECPublicKey) key).getQ();
ECPublicKeyParameters getKey() {
return key;
}
}

View File

@@ -0,0 +1,30 @@
package net.sf.briar.crypto;
import net.sf.briar.api.crypto.SecretKey;
import net.sf.briar.util.ByteUtils;
class SecretKeyImpl implements SecretKey {
private final byte[] key;
private boolean erased = false; // Locking: this
SecretKeyImpl(byte[] key) {
this.key = key;
}
public synchronized byte[] getEncoded() {
if(erased) throw new IllegalStateException();
return key;
}
public SecretKey copy() {
return new SecretKeyImpl(key.clone());
}
public synchronized void erase() {
if(erased) throw new IllegalStateException();
ByteUtils.erase(key);
erased = true;
}
}

View File

@@ -0,0 +1,58 @@
package net.sf.briar.crypto;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import net.sf.briar.api.crypto.PrivateKey;
import net.sf.briar.api.crypto.PublicKey;
import net.sf.briar.api.crypto.Signature;
import org.spongycastle.crypto.digests.SHA384Digest;
import org.spongycastle.crypto.params.ECPrivateKeyParameters;
import org.spongycastle.crypto.params.ECPublicKeyParameters;
import org.spongycastle.crypto.params.ParametersWithRandom;
import org.spongycastle.crypto.signers.DSADigestSigner;
import org.spongycastle.crypto.signers.ECDSASigner;
class SignatureImpl implements Signature {
private final SecureRandom secureRandom;
private final DSADigestSigner signer;
SignatureImpl(SecureRandom secureRandom) {
this.secureRandom = secureRandom;
signer = new DSADigestSigner(new ECDSASigner(), new SHA384Digest());
}
public void initSign(PrivateKey k) throws GeneralSecurityException {
if(!(k instanceof Sec1PrivateKey)) throw new GeneralSecurityException();
ECPrivateKeyParameters priv = ((Sec1PrivateKey) k).getKey();
signer.init(true, new ParametersWithRandom(priv, secureRandom));
}
public void initVerify(PublicKey k) throws GeneralSecurityException {
if(!(k instanceof Sec1PublicKey)) throw new GeneralSecurityException();
ECPublicKeyParameters pub = ((Sec1PublicKey) k).getKey();
signer.init(false, pub);
}
public void update(byte b) {
signer.update(b);
}
public void update(byte[] b) {
update(b, 0, b.length);
}
public void update(byte[] b, int off, int len) {
signer.update(b, off, len);
}
public byte[] sign() {
return signer.generateSignature();
}
public boolean verify(byte[] signature) {
return signer.verifySignature(signature);
}
}

View File

@@ -13,8 +13,6 @@ import static net.sf.briar.api.messaging.Rating.GOOD;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.Signature;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -36,9 +34,11 @@ import net.sf.briar.api.UniqueId;
import net.sf.briar.api.clock.Clock;
import net.sf.briar.api.crypto.CryptoComponent;
import net.sf.briar.api.crypto.KeyManager;
import net.sf.briar.api.crypto.KeyPair;
import net.sf.briar.api.crypto.KeyParser;
import net.sf.briar.api.crypto.MessageDigest;
import net.sf.briar.api.crypto.PseudoRandom;
import net.sf.briar.api.crypto.Signature;
import net.sf.briar.api.db.DatabaseComponent;
import net.sf.briar.api.db.DbException;
import net.sf.briar.api.db.NoSuchTransportException;

View File

@@ -16,14 +16,14 @@ import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.Signature;
import net.sf.briar.api.Author;
import net.sf.briar.api.clock.Clock;
import net.sf.briar.api.crypto.CryptoComponent;
import net.sf.briar.api.crypto.MessageDigest;
import net.sf.briar.api.crypto.PrivateKey;
import net.sf.briar.api.crypto.Signature;
import net.sf.briar.api.messaging.Group;
import net.sf.briar.api.messaging.Message;
import net.sf.briar.api.messaging.MessageFactory;

View File

@@ -1,13 +1,13 @@
package net.sf.briar.messaging;
import java.security.GeneralSecurityException;
import java.security.PublicKey;
import java.security.Signature;
import net.sf.briar.api.Author;
import net.sf.briar.api.crypto.CryptoComponent;
import net.sf.briar.api.crypto.KeyParser;
import net.sf.briar.api.crypto.MessageDigest;
import net.sf.briar.api.crypto.PublicKey;
import net.sf.briar.api.crypto.Signature;
import net.sf.briar.api.messaging.Group;
import net.sf.briar.api.messaging.Message;
import net.sf.briar.api.messaging.MessageId;

View File

@@ -3,7 +3,7 @@ package net.sf.briar.transport;
import java.io.InputStream;
import net.sf.briar.api.crypto.CryptoComponent;
import net.sf.briar.api.crypto.ErasableKey;
import net.sf.briar.api.crypto.SecretKey;
import net.sf.briar.api.transport.ConnectionContext;
import net.sf.briar.api.transport.ConnectionReader;
import net.sf.briar.api.transport.ConnectionReaderFactory;
@@ -26,7 +26,7 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory {
long connection = ctx.getConnectionNumber();
boolean weAreAlice = ctx.getAlice();
boolean initiatorIsAlice = incoming ? !weAreAlice : weAreAlice;
ErasableKey frameKey = crypto.deriveFrameKey(secret, connection,
SecretKey frameKey = crypto.deriveFrameKey(secret, connection,
initiatorIsAlice, initiator);
FrameReader encryption = new IncomingEncryptionLayer(in,
crypto.getFrameCipher(), frameKey, maxFrameLength);
@@ -35,7 +35,7 @@ class ConnectionReaderFactoryImpl implements ConnectionReaderFactory {
public ConnectionReader createInvitationConnectionReader(InputStream in,
int maxFrameLength, byte[] secret, boolean alice) {
ErasableKey frameKey = crypto.deriveFrameKey(secret, 0, true, alice);
SecretKey frameKey = crypto.deriveFrameKey(secret, 0, true, alice);
FrameReader encryption = new IncomingEncryptionLayer(in,
crypto.getFrameCipher(), frameKey, maxFrameLength);
return new ConnectionReaderImpl(encryption, maxFrameLength);

View File

@@ -5,7 +5,7 @@ import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
import java.io.OutputStream;
import net.sf.briar.api.crypto.CryptoComponent;
import net.sf.briar.api.crypto.ErasableKey;
import net.sf.briar.api.crypto.SecretKey;
import net.sf.briar.api.transport.ConnectionContext;
import net.sf.briar.api.transport.ConnectionWriter;
import net.sf.briar.api.transport.ConnectionWriterFactory;
@@ -28,12 +28,12 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
long connection = ctx.getConnectionNumber();
boolean weAreAlice = ctx.getAlice();
boolean initiatorIsAlice = incoming ? !weAreAlice : weAreAlice;
ErasableKey frameKey = crypto.deriveFrameKey(secret, connection,
SecretKey frameKey = crypto.deriveFrameKey(secret, connection,
initiatorIsAlice, initiator);
FrameWriter encryption;
if(initiator) {
byte[] tag = new byte[TAG_LENGTH];
ErasableKey tagKey = crypto.deriveTagKey(secret, initiatorIsAlice);
SecretKey tagKey = crypto.deriveTagKey(secret, initiatorIsAlice);
crypto.encodeTag(tag, tagKey, connection);
tagKey.erase();
encryption = new OutgoingEncryptionLayer(out, capacity,
@@ -47,7 +47,7 @@ class ConnectionWriterFactoryImpl implements ConnectionWriterFactory {
public ConnectionWriter createInvitationConnectionWriter(OutputStream out,
int maxFrameLength, byte[] secret, boolean alice) {
ErasableKey frameKey = crypto.deriveFrameKey(secret, 0, true, alice);
SecretKey frameKey = crypto.deriveFrameKey(secret, 0, true, alice);
FrameWriter encryption = new OutgoingEncryptionLayer(out,
Long.MAX_VALUE, crypto.getFrameCipher(), frameKey,
maxFrameLength);

View File

@@ -13,13 +13,13 @@ import java.security.GeneralSecurityException;
import net.sf.briar.api.FormatException;
import net.sf.briar.api.crypto.AuthenticatedCipher;
import net.sf.briar.api.crypto.ErasableKey;
import net.sf.briar.api.crypto.SecretKey;
class IncomingEncryptionLayer implements FrameReader {
private final InputStream in;
private final AuthenticatedCipher frameCipher;
private final ErasableKey frameKey;
private final SecretKey frameKey;
private final byte[] iv, aad, ciphertext;
private final int frameLength;
@@ -27,7 +27,7 @@ class IncomingEncryptionLayer implements FrameReader {
private boolean finalFrame;
IncomingEncryptionLayer(InputStream in, AuthenticatedCipher frameCipher,
ErasableKey frameKey, int frameLength) {
SecretKey frameKey, int frameLength) {
this.in = in;
this.frameCipher = frameCipher;
this.frameKey = frameKey;

View File

@@ -12,13 +12,13 @@ import java.io.OutputStream;
import java.security.GeneralSecurityException;
import net.sf.briar.api.crypto.AuthenticatedCipher;
import net.sf.briar.api.crypto.ErasableKey;
import net.sf.briar.api.crypto.SecretKey;
class OutgoingEncryptionLayer implements FrameWriter {
private final OutputStream out;
private final AuthenticatedCipher frameCipher;
private final ErasableKey frameKey;
private final SecretKey frameKey;
private final byte[] tag, iv, aad, ciphertext;
private final int frameLength, maxPayloadLength;
@@ -27,7 +27,7 @@ class OutgoingEncryptionLayer implements FrameWriter {
/** Constructor for the initiator's side of a connection. */
OutgoingEncryptionLayer(OutputStream out, long capacity,
AuthenticatedCipher frameCipher, ErasableKey frameKey,
AuthenticatedCipher frameCipher, SecretKey frameKey,
int frameLength, byte[] tag) {
this.out = out;
this.capacity = capacity;
@@ -45,7 +45,7 @@ class OutgoingEncryptionLayer implements FrameWriter {
/** Constructor for the responder's side of a connection. */
OutgoingEncryptionLayer(OutputStream out, long capacity,
AuthenticatedCipher frameCipher, ErasableKey frameKey,
AuthenticatedCipher frameCipher, SecretKey frameKey,
int frameLength) {
this.out = out;
this.capacity = capacity;

View File

@@ -11,7 +11,7 @@ import net.sf.briar.api.Bytes;
import net.sf.briar.api.ContactId;
import net.sf.briar.api.TransportId;
import net.sf.briar.api.crypto.CryptoComponent;
import net.sf.briar.api.crypto.ErasableKey;
import net.sf.briar.api.crypto.SecretKey;
import net.sf.briar.api.db.DatabaseComponent;
import net.sf.briar.api.db.DbException;
import net.sf.briar.api.transport.ConnectionContext;
@@ -41,7 +41,7 @@ class TransportConnectionRecogniser {
TagContext t = tagMap.remove(new Bytes(tag));
if(t == null) return null; // The tag was not expected
// Update the connection window and the expected tags
ErasableKey key = crypto.deriveTagKey(t.secret, !t.alice);
SecretKey key = crypto.deriveTagKey(t.secret, !t.alice);
for(long connection : t.window.setSeen(t.connection)) {
byte[] tag1 = new byte[TAG_LENGTH];
crypto.encodeTag(tag1, key, connection);
@@ -72,7 +72,7 @@ class TransportConnectionRecogniser {
long centre = s.getWindowCentre();
byte[] bitmap = s.getWindowBitmap();
// Create the connection window and the expected tags
ErasableKey key = crypto.deriveTagKey(secret, !alice);
SecretKey key = crypto.deriveTagKey(secret, !alice);
ConnectionWindow window = new ConnectionWindow(centre, bitmap);
for(long connection : window.getUnseen()) {
byte[] tag = new byte[TAG_LENGTH];
@@ -98,7 +98,7 @@ class TransportConnectionRecogniser {
// Locking: this
private void removeSecret(RemovalContext r) {
// Remove the expected tags
ErasableKey key = crypto.deriveTagKey(r.secret, !r.alice);
SecretKey key = crypto.deriveTagKey(r.secret, !r.alice);
byte[] tag = new byte[TAG_LENGTH];
for(long connection : r.window.getUnseen()) {
crypto.encodeTag(tag, key, connection);