mirror of
https://github.com/moparisthebest/open-keychain
synced 2025-02-23 06:12:20 -05:00
add support for user attributes (during canonicalization)
This commit is contained in:
parent
e0847cafaf
commit
8408113322
@ -416,6 +416,21 @@ public abstract class OperationResult implements Parcelable {
|
|||||||
MSG_KC_UID_REVOKE_OLD (LogLevel.DEBUG, R.string.msg_kc_uid_revoke_old),
|
MSG_KC_UID_REVOKE_OLD (LogLevel.DEBUG, R.string.msg_kc_uid_revoke_old),
|
||||||
MSG_KC_UID_REMOVE (LogLevel.DEBUG, R.string.msg_kc_uid_remove),
|
MSG_KC_UID_REMOVE (LogLevel.DEBUG, R.string.msg_kc_uid_remove),
|
||||||
MSG_KC_UID_WARN_ENCODING (LogLevel.WARN, R.string.msg_kc_uid_warn_encoding),
|
MSG_KC_UID_WARN_ENCODING (LogLevel.WARN, R.string.msg_kc_uid_warn_encoding),
|
||||||
|
MSG_KC_UAT_JPEG (LogLevel.DEBUG, R.string.msg_kc_uat_jpeg),
|
||||||
|
MSG_KC_UAT_UNKNOWN (LogLevel.DEBUG, R.string.msg_kc_uat_unknown),
|
||||||
|
MSG_KC_UAT_BAD_ERR (LogLevel.WARN, R.string.msg_kc_uat_bad_err),
|
||||||
|
MSG_KC_UAT_BAD_LOCAL (LogLevel.WARN, R.string.msg_kc_uat_bad_local),
|
||||||
|
MSG_KC_UAT_BAD_TIME (LogLevel.WARN, R.string.msg_kc_uat_bad_time),
|
||||||
|
MSG_KC_UAT_BAD_TYPE (LogLevel.WARN, R.string.msg_kc_uat_bad_type),
|
||||||
|
MSG_KC_UAT_BAD (LogLevel.WARN, R.string.msg_kc_uat_bad),
|
||||||
|
MSG_KC_UAT_CERT_DUP (LogLevel.DEBUG, R.string.msg_kc_uat_cert_dup),
|
||||||
|
MSG_KC_UAT_DUP (LogLevel.DEBUG, R.string.msg_kc_uat_dup),
|
||||||
|
MSG_KC_UAT_FOREIGN (LogLevel.DEBUG, R.string.msg_kc_uat_foreign),
|
||||||
|
MSG_KC_UAT_NO_CERT (LogLevel.DEBUG, R.string.msg_kc_uat_no_cert),
|
||||||
|
MSG_KC_UAT_REVOKE_DUP (LogLevel.DEBUG, R.string.msg_kc_uat_revoke_dup),
|
||||||
|
MSG_KC_UAT_REVOKE_OLD (LogLevel.DEBUG, R.string.msg_kc_uat_revoke_old),
|
||||||
|
MSG_KC_UAT_REMOVE (LogLevel.DEBUG, R.string.msg_kc_uat_remove),
|
||||||
|
MSG_KC_UAT_WARN_ENCODING (LogLevel.WARN, R.string.msg_kc_uat_warn_encoding),
|
||||||
|
|
||||||
|
|
||||||
// keyring consolidation
|
// keyring consolidation
|
||||||
|
@ -21,6 +21,7 @@ package org.sufficientlysecure.keychain.pgp;
|
|||||||
import org.spongycastle.bcpg.ArmoredOutputStream;
|
import org.spongycastle.bcpg.ArmoredOutputStream;
|
||||||
import org.spongycastle.bcpg.PublicKeyAlgorithmTags;
|
import org.spongycastle.bcpg.PublicKeyAlgorithmTags;
|
||||||
import org.spongycastle.bcpg.SignatureSubpacketTags;
|
import org.spongycastle.bcpg.SignatureSubpacketTags;
|
||||||
|
import org.spongycastle.bcpg.UserAttributeSubpacketTags;
|
||||||
import org.spongycastle.bcpg.sig.KeyFlags;
|
import org.spongycastle.bcpg.sig.KeyFlags;
|
||||||
import org.spongycastle.openpgp.PGPKeyRing;
|
import org.spongycastle.openpgp.PGPKeyRing;
|
||||||
import org.spongycastle.openpgp.PGPObjectFactory;
|
import org.spongycastle.openpgp.PGPObjectFactory;
|
||||||
@ -30,6 +31,7 @@ import org.spongycastle.openpgp.PGPSecretKey;
|
|||||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
||||||
import org.spongycastle.openpgp.PGPSignature;
|
import org.spongycastle.openpgp.PGPSignature;
|
||||||
import org.spongycastle.openpgp.PGPSignatureList;
|
import org.spongycastle.openpgp.PGPSignatureList;
|
||||||
|
import org.spongycastle.openpgp.PGPUserAttributeSubpacketVector;
|
||||||
import org.spongycastle.openpgp.PGPUtil;
|
import org.spongycastle.openpgp.PGPUtil;
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
|
import org.spongycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
@ -605,6 +607,170 @@ public class UncachedKeyRing {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArrayList<PGPUserAttributeSubpacketVector> processedUserAttributes = new ArrayList<>();
|
||||||
|
for (PGPUserAttributeSubpacketVector userAttribute :
|
||||||
|
new IterableIterator<PGPUserAttributeSubpacketVector>(masterKey.getUserAttributes())) {
|
||||||
|
|
||||||
|
if (userAttribute.getSubpacket(UserAttributeSubpacketTags.IMAGE_ATTRIBUTE) != null) {
|
||||||
|
log.add(LogType.MSG_KC_UAT_JPEG, indent);
|
||||||
|
} else {
|
||||||
|
log.add(LogType.MSG_KC_UAT_UNKNOWN, indent);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
indent += 1;
|
||||||
|
|
||||||
|
// check for duplicate user attributes
|
||||||
|
if (processedUserAttributes.contains(userAttribute)) {
|
||||||
|
log.add(LogType.MSG_KC_UAT_DUP, indent);
|
||||||
|
// strip out the first found user id with this name
|
||||||
|
modified = PGPPublicKey.removeCertification(modified, userAttribute);
|
||||||
|
}
|
||||||
|
processedUserAttributes.add(userAttribute);
|
||||||
|
|
||||||
|
PGPSignature selfCert = null;
|
||||||
|
revocation = null;
|
||||||
|
|
||||||
|
// look through signatures for this specific user id
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Iterator<PGPSignature> signaturesIt = masterKey.getSignaturesForUserAttribute(userAttribute);
|
||||||
|
if (signaturesIt != null) {
|
||||||
|
for (PGPSignature zert : new IterableIterator<PGPSignature>(signaturesIt)) {
|
||||||
|
WrappedSignature cert = new WrappedSignature(zert);
|
||||||
|
long certId = cert.getKeyId();
|
||||||
|
|
||||||
|
int type = zert.getSignatureType();
|
||||||
|
if (type != PGPSignature.DEFAULT_CERTIFICATION
|
||||||
|
&& type != PGPSignature.NO_CERTIFICATION
|
||||||
|
&& type != PGPSignature.CASUAL_CERTIFICATION
|
||||||
|
&& type != PGPSignature.POSITIVE_CERTIFICATION
|
||||||
|
&& type != PGPSignature.CERTIFICATION_REVOCATION) {
|
||||||
|
log.add(LogType.MSG_KC_UAT_BAD_TYPE,
|
||||||
|
indent, "0x" + Integer.toString(zert.getSignatureType(), 16));
|
||||||
|
modified = PGPPublicKey.removeCertification(modified, userAttribute, zert);
|
||||||
|
badCerts += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cert.getCreationTime().after(nowPlusOneDay)) {
|
||||||
|
// Creation date in the future? No way!
|
||||||
|
log.add(LogType.MSG_KC_UAT_BAD_TIME, indent);
|
||||||
|
modified = PGPPublicKey.removeCertification(modified, userAttribute, zert);
|
||||||
|
badCerts += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cert.isLocal()) {
|
||||||
|
// Creation date in the future? No way!
|
||||||
|
log.add(LogType.MSG_KC_UAT_BAD_LOCAL, indent);
|
||||||
|
modified = PGPPublicKey.removeCertification(modified, userAttribute, zert);
|
||||||
|
badCerts += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is a foreign signature, ...
|
||||||
|
if (certId != masterKeyId) {
|
||||||
|
// never mind any further for public keys, but remove them from secret ones
|
||||||
|
if (isSecret()) {
|
||||||
|
log.add(LogType.MSG_KC_UAT_FOREIGN,
|
||||||
|
indent, KeyFormattingUtils.convertKeyIdToHex(certId));
|
||||||
|
modified = PGPPublicKey.removeCertification(modified, userAttribute, zert);
|
||||||
|
badCerts += 1;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, first make sure it checks out
|
||||||
|
try {
|
||||||
|
cert.init(masterKey);
|
||||||
|
if (!cert.verifySignature(masterKey, userAttribute)) {
|
||||||
|
log.add(LogType.MSG_KC_UAT_BAD,
|
||||||
|
indent);
|
||||||
|
modified = PGPPublicKey.removeCertification(modified, userAttribute, zert);
|
||||||
|
badCerts += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} catch (PgpGeneralException e) {
|
||||||
|
log.add(LogType.MSG_KC_UAT_BAD_ERR,
|
||||||
|
indent);
|
||||||
|
modified = PGPPublicKey.removeCertification(modified, userAttribute, zert);
|
||||||
|
badCerts += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case PGPSignature.DEFAULT_CERTIFICATION:
|
||||||
|
case PGPSignature.NO_CERTIFICATION:
|
||||||
|
case PGPSignature.CASUAL_CERTIFICATION:
|
||||||
|
case PGPSignature.POSITIVE_CERTIFICATION:
|
||||||
|
if (selfCert == null) {
|
||||||
|
selfCert = zert;
|
||||||
|
} else if (selfCert.getCreationTime().before(cert.getCreationTime())) {
|
||||||
|
log.add(LogType.MSG_KC_UAT_CERT_DUP,
|
||||||
|
indent);
|
||||||
|
modified = PGPPublicKey.removeCertification(modified, userAttribute, selfCert);
|
||||||
|
redundantCerts += 1;
|
||||||
|
selfCert = zert;
|
||||||
|
} else {
|
||||||
|
log.add(LogType.MSG_KC_UAT_CERT_DUP,
|
||||||
|
indent);
|
||||||
|
modified = PGPPublicKey.removeCertification(modified, userAttribute, zert);
|
||||||
|
redundantCerts += 1;
|
||||||
|
}
|
||||||
|
// If there is a revocation certificate, and it's older than this, drop it
|
||||||
|
if (revocation != null
|
||||||
|
&& revocation.getCreationTime().before(selfCert.getCreationTime())) {
|
||||||
|
log.add(LogType.MSG_KC_UAT_REVOKE_OLD,
|
||||||
|
indent);
|
||||||
|
modified = PGPPublicKey.removeCertification(modified, userAttribute, revocation);
|
||||||
|
revocation = null;
|
||||||
|
redundantCerts += 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PGPSignature.CERTIFICATION_REVOCATION:
|
||||||
|
// If this is older than the (latest) self cert, drop it
|
||||||
|
if (selfCert != null && selfCert.getCreationTime().after(zert.getCreationTime())) {
|
||||||
|
log.add(LogType.MSG_KC_UAT_REVOKE_OLD,
|
||||||
|
indent);
|
||||||
|
modified = PGPPublicKey.removeCertification(modified, userAttribute, zert);
|
||||||
|
redundantCerts += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// first revocation? remember it.
|
||||||
|
if (revocation == null) {
|
||||||
|
revocation = zert;
|
||||||
|
// more revocations? at least one is superfluous, then.
|
||||||
|
} else if (revocation.getCreationTime().before(cert.getCreationTime())) {
|
||||||
|
log.add(LogType.MSG_KC_UAT_REVOKE_DUP,
|
||||||
|
indent);
|
||||||
|
modified = PGPPublicKey.removeCertification(modified, userAttribute, revocation);
|
||||||
|
redundantCerts += 1;
|
||||||
|
revocation = zert;
|
||||||
|
} else {
|
||||||
|
log.add(LogType.MSG_KC_UAT_REVOKE_DUP,
|
||||||
|
indent);
|
||||||
|
modified = PGPPublicKey.removeCertification(modified, userAttribute, zert);
|
||||||
|
redundantCerts += 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no valid certificate (if only a revocation) remains, drop it
|
||||||
|
if (selfCert == null && revocation == null) {
|
||||||
|
log.add(LogType.MSG_KC_UAT_REMOVE,
|
||||||
|
indent);
|
||||||
|
modified = PGPPublicKey.removeCertification(modified, userAttribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
indent -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Replace modified key in the keyring
|
// Replace modified key in the keyring
|
||||||
ring = replacePublicKey(ring, modified);
|
ring = replacePublicKey(ring, modified);
|
||||||
indent -= 1;
|
indent -= 1;
|
||||||
|
@ -29,6 +29,7 @@ import org.spongycastle.openpgp.PGPObjectFactory;
|
|||||||
import org.spongycastle.openpgp.PGPPublicKey;
|
import org.spongycastle.openpgp.PGPPublicKey;
|
||||||
import org.spongycastle.openpgp.PGPSignature;
|
import org.spongycastle.openpgp.PGPSignature;
|
||||||
import org.spongycastle.openpgp.PGPSignatureList;
|
import org.spongycastle.openpgp.PGPSignatureList;
|
||||||
|
import org.spongycastle.openpgp.PGPUserAttributeSubpacketVector;
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
|
import org.spongycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProvider;
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||||
@ -199,6 +200,14 @@ public class WrappedSignature {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean verifySignature(PGPPublicKey key, PGPUserAttributeSubpacketVector attribute) throws PgpGeneralException {
|
||||||
|
try {
|
||||||
|
return mSig.verifyCertification(attribute, key);
|
||||||
|
} catch (PGPException e) {
|
||||||
|
throw new PgpGeneralException("Error!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean verifySignature(UncachedPublicKey key, byte[] rawUserId) throws PgpGeneralException {
|
public boolean verifySignature(UncachedPublicKey key, byte[] rawUserId) throws PgpGeneralException {
|
||||||
return verifySignature(key.getPublicKey(), rawUserId);
|
return verifySignature(key.getPublicKey(), rawUserId);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,160 @@
|
|||||||
|
package org.sufficientlysecure.keychain.pgp.affirmation;
|
||||||
|
|
||||||
|
import org.spongycastle.bcpg.UserAttributeSubpacket;
|
||||||
|
import org.spongycastle.util.Strings;
|
||||||
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class LinkedIdentity {
|
||||||
|
|
||||||
|
protected byte[] mData;
|
||||||
|
public final String mNonce;
|
||||||
|
public final URI mSubUri;
|
||||||
|
final Set<String> mFlags;
|
||||||
|
final HashMap<String,String> mParams;
|
||||||
|
|
||||||
|
protected LinkedIdentity(byte[] data, String nonce, Set<String> flags,
|
||||||
|
HashMap<String, String> params, URI subUri) {
|
||||||
|
if ( ! nonce.matches("[0-9a-zA-Z]+")) {
|
||||||
|
throw new AssertionError("bug: nonce must be hexstring!");
|
||||||
|
}
|
||||||
|
|
||||||
|
mData = data;
|
||||||
|
mNonce = nonce;
|
||||||
|
mFlags = flags;
|
||||||
|
mParams = params;
|
||||||
|
mSubUri = subUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinkedIdentity(String nonce, Set<String> flags,
|
||||||
|
HashMap<String, String> params, URI subUri) {
|
||||||
|
this(null, nonce, flags, params, subUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] encode() {
|
||||||
|
if (mData != null) {
|
||||||
|
return mData;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
b.append("pgpid:");
|
||||||
|
|
||||||
|
// add flags
|
||||||
|
if (mFlags != null) {
|
||||||
|
boolean first = true;
|
||||||
|
for (String flag : mFlags) {
|
||||||
|
if (!first) {
|
||||||
|
b.append(";");
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
b.append(flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add parameters
|
||||||
|
if (mParams != null) {
|
||||||
|
boolean first = true;
|
||||||
|
Iterator<Entry<String, String>> it = mParams.entrySet().iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
if (!first) {
|
||||||
|
b.append(";");
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
Entry<String, String> entry = it.next();
|
||||||
|
b.append(entry.getKey()).append("=").append(entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b.append("@");
|
||||||
|
b.append(mSubUri);
|
||||||
|
|
||||||
|
byte[] nonceBytes = Hex.decode(mNonce);
|
||||||
|
byte[] data = Strings.toUTF8ByteArray(b.toString());
|
||||||
|
|
||||||
|
byte[] result = new byte[data.length+12];
|
||||||
|
System.arraycopy(nonceBytes, 0, result, 0, 12);
|
||||||
|
System.arraycopy(data, 0, result, 12, result.length);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This method parses an affirmation from a UserAttributeSubpacket, or returns null if the
|
||||||
|
* subpacket can not be parsed as a valid affirmation.
|
||||||
|
*/
|
||||||
|
public static LinkedIdentity parseAffirmation(UserAttributeSubpacket subpacket) {
|
||||||
|
if (subpacket.getType() != 100) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] data = subpacket.getData();
|
||||||
|
String nonce = Hex.toHexString(data, 0, 12);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return parseUri(nonce, Strings.fromUTF8ByteArray(Arrays.copyOfRange(data, 12, data.length)));
|
||||||
|
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
Log.e(Constants.TAG, "error parsing uri in (suspected) affirmation packet");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static LinkedIdentity parseUri (String nonce, String uriString) {
|
||||||
|
URI uri = URI.create(uriString);
|
||||||
|
|
||||||
|
if ("pgpid".equals(uri.getScheme())) {
|
||||||
|
Log.e(Constants.TAG, "unknown uri scheme in (suspected) affirmation packet");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!uri.isOpaque()) {
|
||||||
|
Log.e(Constants.TAG, "non-opaque uri in (suspected) affirmation packet");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String specific = uri.getSchemeSpecificPart();
|
||||||
|
if (!specific.contains("@")) {
|
||||||
|
Log.e(Constants.TAG, "unknown uri scheme in affirmation packet");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] pieces = specific.split("@", 2);
|
||||||
|
URI subUri = URI.create(pieces[1]);
|
||||||
|
|
||||||
|
Set<String> flags = new HashSet<String>();
|
||||||
|
HashMap<String,String> params = new HashMap<String,String>();
|
||||||
|
{
|
||||||
|
String[] rawParams = pieces[0].split(";");
|
||||||
|
for (String param : rawParams) {
|
||||||
|
String[] p = param.split("=", 2);
|
||||||
|
if (p.length == 1) {
|
||||||
|
flags.add(param);
|
||||||
|
} else {
|
||||||
|
params.put(p[0], p[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new LinkedIdentity(nonce, flags, params, subUri);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String generateNonce() {
|
||||||
|
// TODO make this actually random
|
||||||
|
// byte[] data = new byte[96];
|
||||||
|
// new SecureRandom().nextBytes(data);
|
||||||
|
// return Hex.toHexString(data);
|
||||||
|
|
||||||
|
// debug for now
|
||||||
|
return "0123456789ABCDEF01234567";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -761,8 +761,23 @@
|
|||||||
<string name="msg_kc_uid_revoke_old">"Removing outdated revocation certificate for user ID '%s'"</string>
|
<string name="msg_kc_uid_revoke_old">"Removing outdated revocation certificate for user ID '%s'"</string>
|
||||||
<string name="msg_kc_uid_no_cert">"No valid self-certificate found for user ID '%s', removing from ring"</string>
|
<string name="msg_kc_uid_no_cert">"No valid self-certificate found for user ID '%s', removing from ring"</string>
|
||||||
<string name="msg_kc_uid_remove">"Removing invalid user ID '%s'"</string>
|
<string name="msg_kc_uid_remove">"Removing invalid user ID '%s'"</string>
|
||||||
<string name="msg_kc_uid_dup">"Removing duplicate user ID '%s'. The secret key contained two of them. This may result in missing certificates!"</string>
|
<string name="msg_kc_uid_dup">"Removing duplicate user ID '%s'. The keyring contained two of them. This may result in missing certificates!"</string>
|
||||||
<string name="msg_kc_uid_warn_encoding">"User id does not verify as UTF-8!"</string>
|
<string name="msg_kc_uid_warn_encoding">"User id does not verify as UTF-8!"</string>
|
||||||
|
<string name="msg_kc_uat_jpeg">"Processing user attribute of type JPEG"</string>
|
||||||
|
<string name="msg_kc_uat_unknown">"Processing user attribute of unknown type"</string>
|
||||||
|
<string name="msg_kc_uat_bad_err">"Removing bad self certificate for user attribute"</string>
|
||||||
|
<string name="msg_kc_uat_bad_local">"Removing user attribute certificate with 'local' flag"</string>
|
||||||
|
<string name="msg_kc_uat_bad_time">"Removing user attribute with future timestamp"</string>
|
||||||
|
<string name="msg_kc_uat_bad_type">"Removing user attribute certificate of unknown type (%s)"</string>
|
||||||
|
<string name="msg_kc_uat_bad">"Removing bad self certificate for user attribute"</string>
|
||||||
|
<string name="msg_kc_uat_cert_dup">"Removing outdated self certificate for user attribute"</string>
|
||||||
|
<string name="msg_kc_uat_dup">"Removing duplicate user attribute. The keyring contained two of them. This may result in missing certificates!"</string>
|
||||||
|
<string name="msg_kc_uat_foreign">"Removing foreign user attribute certificate by"</string>
|
||||||
|
<string name="msg_kc_uat_revoke_dup">"Removing redundant revocation certificate for user attribute"</string>
|
||||||
|
<string name="msg_kc_uat_revoke_old">"Removing outdated revocation certificate for user attribute"</string>
|
||||||
|
<string name="msg_kc_uat_no_cert">"No valid self-certificate found for user attribute, removing from ring"</string>
|
||||||
|
<string name="msg_kc_uat_remove">"Removing invalid user attribute"</string>
|
||||||
|
<string name="msg_kc_uat_warn_encoding">"User id does not verify as UTF-8!"</string>
|
||||||
|
|
||||||
<!-- Keyring merging log entries -->
|
<!-- Keyring merging log entries -->
|
||||||
<string name="msg_mg_error_secret_dummy">"New public subkey found, but secret subkey dummy generation is not supported!"</string>
|
<string name="msg_mg_error_secret_dummy">"New public subkey found, but secret subkey dummy generation is not supported!"</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user