refactor the storage of signing keys

This commit is contained in:
zzz
2010-02-05 19:19:33 +00:00
parent 2f8b55ceda
commit 3aebe45a7d

View File

@ -8,6 +8,8 @@ import java.io.IOException;
import java.io.SequenceInputStream; import java.io.SequenceInputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import net.i2p.CoreVersion; import net.i2p.CoreVersion;
@ -108,8 +110,10 @@ D8usM7Dxp5yrDrCYZ5AIijc=
private static I2PAppContext _context; private static I2PAppContext _context;
private Log _log; private Log _log;
private ArrayList _trustedKeys; private Map<SigningPublicKey, String> _trustedKeys;
private String _newVersion; private String _newVersion;
/** 172 */
private static final int KEYSIZE_B64_BYTES = 2 + (SigningPublicKey.KEYSIZE_BYTES * 4 / 3);
/** /**
* Constructs a new <code>TrustedUpdate</code> with the default global * Constructs a new <code>TrustedUpdate</code> with the default global
@ -128,7 +132,7 @@ D8usM7Dxp5yrDrCYZ5AIijc=
public TrustedUpdate(I2PAppContext context) { public TrustedUpdate(I2PAppContext context) {
_context = context; _context = context;
_log = _context.logManager().getLog(TrustedUpdate.class); _log = _context.logManager().getLog(TrustedUpdate.class);
_trustedKeys = new ArrayList(); _trustedKeys = new HashMap(4);
_newVersion = null; _newVersion = null;
String propertyTrustedKeys = context.getProperty(PROP_TRUSTED_KEYS); String propertyTrustedKeys = context.getProperty(PROP_TRUSTED_KEYS);
@ -137,16 +141,43 @@ D8usM7Dxp5yrDrCYZ5AIijc=
StringTokenizer propertyTrustedKeysTokens = new StringTokenizer(propertyTrustedKeys, " ,\r\n"); StringTokenizer propertyTrustedKeysTokens = new StringTokenizer(propertyTrustedKeys, " ,\r\n");
while (propertyTrustedKeysTokens.hasMoreTokens()) while (propertyTrustedKeysTokens.hasMoreTokens())
_trustedKeys.add(propertyTrustedKeysTokens.nextToken().trim()); addKey(propertyTrustedKeysTokens.nextToken().trim(), "");
} else { } else {
_trustedKeys.add(DEFAULT_TRUSTED_KEY); addKey(DEFAULT_TRUSTED_KEY, "jrandom@mail.i2p");
_trustedKeys.add(DEFAULT_TRUSTED_KEY2); addKey(DEFAULT_TRUSTED_KEY2, "zzz@mail.i2p");
//addKey(DEFAULT_TRUSTED_KEY3, "complication@mail.i2p");
} }
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug("TrustedUpdate created, trusting " + _trustedKeys.size() + " keys."); _log.debug("TrustedUpdate created, trusting " + _trustedKeys.size() + " keys.");
} }
/**
* Duplicate keys or names rejected,
* except that duplicate empty names are allowed
* @since 0.7.12
* @return true if successful
*/
public boolean addKey(String key, String name) {
SigningPublicKey signingPublicKey = new SigningPublicKey();
try {
// fromBase64() won't reject a string that is too long
if (key.length() != KEYSIZE_B64_BYTES)
throw new DataFormatException("x");
signingPublicKey.fromBase64(key);
} catch (DataFormatException dfe) {
_log.error("Bad signing key for " + name + " : " + key);
return false;
}
if (_trustedKeys.containsKey(signingPublicKey) ||
((!name.equals("")) && _trustedKeys.containsValue(name))) {
_log.error("Duplicate signing key for " + name + " : " + key);
return false;
}
_trustedKeys.put(signingPublicKey, name);
return true;
}
/** /**
* Parses command line arguments when this class is used from the command * Parses command line arguments when this class is used from the command
* line. * line.
@ -267,23 +298,25 @@ D8usM7Dxp5yrDrCYZ5AIijc=
* *
* @return An <code>ArrayList</code> containting the trusted keys. * @return An <code>ArrayList</code> containting the trusted keys.
*/ */
/***
public ArrayList getTrustedKeys() { public ArrayList getTrustedKeys() {
return _trustedKeys; return _trustedKeys;
} }
***/
/** /**
* Fetches the trusted keys for the current instance. * Fetches the trusted keys for the current instance.
* We could sort it but don't bother.
* *
* @return A <code>String</code> containing the trusted keys, * @return A <code>String</code> containing the trusted keys,
* delimited by CR LF line breaks. * delimited by CR LF line breaks.
*/ */
public String getTrustedKeysString() { public String getTrustedKeysString() {
StringBuilder buf = new StringBuilder(1024); StringBuilder buf = new StringBuilder(1024);
for (int i = 0; i < _trustedKeys.size(); i++) { for (SigningPublicKey spk : _trustedKeys.keySet()) {
// If something already buffered, first add line break. // If something already buffered, first add line break.
if (buf.length() > 0) buf.append("\r\n"); if (buf.length() > 0) buf.append("\r\n");
buf.append((String) _trustedKeys.get(i)); buf.append(spk.toBase64());
} }
return buf.toString(); return buf.toString();
@ -565,18 +598,10 @@ D8usM7Dxp5yrDrCYZ5AIijc=
* <code>false</code>. * <code>false</code>.
*/ */
public boolean verify(File signedFile) { public boolean verify(File signedFile) {
for (int i = 0; i < _trustedKeys.size(); i++) { for (SigningPublicKey signingPublicKey : _trustedKeys.keySet()) {
SigningPublicKey signingPublicKey = new SigningPublicKey(); boolean isValidSignature = verify(signedFile, signingPublicKey);
if (isValidSignature)
try { return true;
signingPublicKey.fromBase64((String)_trustedKeys.get(i));
boolean isValidSignature = verify(signedFile, signingPublicKey);
if (isValidSignature)
return true;
} catch (DataFormatException dfe) {
_log.log(Log.CRIT, "Trusted key " + i + " is not valid");
}
} }
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.WARN))