387 lines
11 KiB
Java
387 lines
11 KiB
Java
/*
|
|
* Copyright (C) 2017 Schürmann & Breitmoser GbR
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
package org.sufficientlysecure.keychain.keyimport;
|
|
|
|
|
|
import java.io.IOException;
|
|
import java.io.Serializable;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.Collections;
|
|
import java.util.Date;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
import android.content.Context;
|
|
import android.os.Parcel;
|
|
import android.os.Parcelable;
|
|
|
|
import org.openintents.openpgp.util.OpenPgpUtils.UserId;
|
|
import org.sufficientlysecure.keychain.pgp.KeyRing;
|
|
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
|
|
import org.sufficientlysecure.keychain.pgp.UncachedPublicKey;
|
|
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
|
|
|
public class ImportKeysListEntry implements Serializable, Parcelable {
|
|
private static final long serialVersionUID = -7797972103284992662L;
|
|
|
|
private ParcelableKeyRing mParcelableKeyRing;
|
|
|
|
private ArrayList<String> mUserIds;
|
|
private HashMap<String, HashSet<String>> mMergedUserIds;
|
|
private ArrayList<Map.Entry<String, HashSet<String>>> mSortedUserIds;
|
|
|
|
private String mKeyIdHex;
|
|
|
|
private boolean mSecretKey;
|
|
private boolean mRevoked;
|
|
private boolean mExpired;
|
|
private boolean mSecure;
|
|
private boolean mUpdated;
|
|
|
|
private Date mDate;
|
|
private byte[] mFingerprint;
|
|
private Integer mBitStrength;
|
|
private String mCurveOid;
|
|
private String mAlgorithm;
|
|
|
|
private UserId mPrimaryUserId;
|
|
private HkpKeyserverAddress mKeyserver;
|
|
private String mFbUsername;
|
|
|
|
private String mQuery;
|
|
private Integer mHashCode = null;
|
|
|
|
public ParcelableKeyRing getParcelableKeyRing() {
|
|
return mParcelableKeyRing;
|
|
}
|
|
|
|
public void setParcelableKeyRing(ParcelableKeyRing parcelableKeyRing) {
|
|
this.mParcelableKeyRing = parcelableKeyRing;
|
|
}
|
|
|
|
public boolean hasSameKeyAs(ImportKeysListEntry other) {
|
|
if (mFingerprint == null || other == null || other.mFingerprint == null) {
|
|
return false;
|
|
}
|
|
return Arrays.equals(mFingerprint, other.mFingerprint);
|
|
}
|
|
|
|
public String getKeyIdHex() {
|
|
return mKeyIdHex;
|
|
}
|
|
|
|
public void setKeyIdHex(String keyIdHex) {
|
|
mKeyIdHex = keyIdHex;
|
|
}
|
|
|
|
public void setKeyId(long keyId) {
|
|
mKeyIdHex = KeyFormattingUtils.convertKeyIdToHex(keyId);
|
|
}
|
|
|
|
public boolean isExpired() {
|
|
return mExpired;
|
|
}
|
|
|
|
public void setExpired(boolean expired) {
|
|
mExpired = expired;
|
|
}
|
|
|
|
public boolean isRevoked() {
|
|
return mRevoked;
|
|
}
|
|
|
|
public void setRevoked(boolean revoked) {
|
|
mRevoked = revoked;
|
|
}
|
|
|
|
public boolean isSecure() {
|
|
return mSecure;
|
|
}
|
|
|
|
public void setSecure(boolean secure) {
|
|
mSecure = secure;
|
|
}
|
|
|
|
public boolean isRevokedOrExpiredOrInsecure() {
|
|
return mRevoked || mExpired || !mSecure;
|
|
}
|
|
|
|
public Date getDate() {
|
|
return mDate;
|
|
}
|
|
|
|
public boolean isUpdated() {
|
|
return mUpdated;
|
|
}
|
|
|
|
public void setUpdated(boolean updated) {
|
|
mUpdated = updated;
|
|
}
|
|
|
|
public void setDate(Date date) {
|
|
mDate = date;
|
|
}
|
|
|
|
public void setFingerprint(byte[] fingerprint) {
|
|
mFingerprint = fingerprint;
|
|
}
|
|
|
|
public byte[] getFingerprint() {
|
|
return mFingerprint;
|
|
}
|
|
|
|
public Integer getBitStrength() {
|
|
return mBitStrength;
|
|
}
|
|
|
|
public String getCurveOid() {
|
|
return mCurveOid;
|
|
}
|
|
|
|
public void setBitStrength(int bitStrength) {
|
|
mBitStrength = bitStrength;
|
|
}
|
|
|
|
public String getAlgorithm() {
|
|
return mAlgorithm;
|
|
}
|
|
|
|
public void setAlgorithm(String algorithm) {
|
|
mAlgorithm = algorithm;
|
|
}
|
|
|
|
public boolean isSecretKey() {
|
|
return mSecretKey;
|
|
}
|
|
|
|
public void setSecretKey(boolean secretKey) {
|
|
mSecretKey = secretKey;
|
|
}
|
|
|
|
public UserId getPrimaryUserId() {
|
|
return mPrimaryUserId;
|
|
}
|
|
|
|
public void setPrimaryUserId(String userId) {
|
|
mPrimaryUserId = KeyRing.splitUserId(userId);
|
|
}
|
|
|
|
public void setPrimaryUserId(UserId primaryUserId) {
|
|
mPrimaryUserId = primaryUserId;
|
|
}
|
|
|
|
public HkpKeyserverAddress getKeyserver() {
|
|
return mKeyserver;
|
|
}
|
|
|
|
public void setKeyserver(HkpKeyserverAddress keyserver) {
|
|
mKeyserver = keyserver;
|
|
}
|
|
|
|
public String getFbUsername() {
|
|
return mFbUsername;
|
|
}
|
|
|
|
public void setFbUsername(String fbUsername) {
|
|
mFbUsername = fbUsername;
|
|
}
|
|
|
|
public String getQuery() {
|
|
return mQuery;
|
|
}
|
|
|
|
public void setQuery(String query) {
|
|
mQuery = query;
|
|
}
|
|
|
|
public int hashCode() {
|
|
return mHashCode != null ? mHashCode : super.hashCode();
|
|
}
|
|
|
|
public List<String> getUserIds() {
|
|
// To ensure choerency, use methods of this class to edit the list
|
|
return Collections.unmodifiableList(mUserIds);
|
|
}
|
|
|
|
public ArrayList<Map.Entry<String, HashSet<String>>> getSortedUserIds() {
|
|
if (mSortedUserIds == null)
|
|
sortMergedUserIds();
|
|
|
|
return mSortedUserIds;
|
|
}
|
|
|
|
public void setUserIds(ArrayList<String> userIds) {
|
|
mUserIds = userIds;
|
|
updateMergedUserIds();
|
|
}
|
|
|
|
public boolean addUserIds(List<String> userIds) {
|
|
boolean modified = false;
|
|
for (String uid : userIds) {
|
|
if (!mUserIds.contains(uid)) {
|
|
mUserIds.add(uid);
|
|
modified = true;
|
|
}
|
|
}
|
|
|
|
if (modified)
|
|
updateMergedUserIds();
|
|
|
|
return modified;
|
|
}
|
|
|
|
/**
|
|
* Constructor for later querying from keyserver
|
|
*/
|
|
public ImportKeysListEntry() {
|
|
// keys from keyserver are always public keys
|
|
mSecretKey = false;
|
|
|
|
mUserIds = new ArrayList<>();
|
|
}
|
|
|
|
/**
|
|
* Constructor based on key object, used for import from NFC, QR Codes, files
|
|
*/
|
|
public ImportKeysListEntry(Context ctx, UncachedKeyRing ring) {
|
|
mSecretKey = ring.isSecret();
|
|
|
|
UncachedPublicKey key = ring.getPublicKey();
|
|
setPrimaryUserId(key.getPrimaryUserIdWithFallback());
|
|
setKeyId(key.getKeyId());
|
|
setFingerprint(key.getFingerprint());
|
|
|
|
// NOTE: Dont use maybe methods for now, they can be wrong.
|
|
mRevoked = false; //key.isMaybeRevoked();
|
|
mExpired = false; //key.isMaybeExpired();
|
|
mSecure = true;
|
|
|
|
mBitStrength = key.getBitStrength();
|
|
mCurveOid = key.getCurveOid();
|
|
int algorithm = key.getAlgorithm();
|
|
mAlgorithm = KeyFormattingUtils.getAlgorithmInfo(ctx, algorithm, mBitStrength, mCurveOid);
|
|
mHashCode = key.hashCode();
|
|
|
|
setUserIds(key.getUnorderedUserIds());
|
|
|
|
try {
|
|
byte[] encoded = ring.getEncoded();
|
|
mParcelableKeyRing = ParcelableKeyRing.createFromEncodedBytes(encoded);
|
|
} catch (IOException ignored) {
|
|
}
|
|
}
|
|
|
|
private void updateMergedUserIds() {
|
|
mMergedUserIds = new HashMap<>();
|
|
for (String userId : mUserIds) {
|
|
UserId userIdSplit = KeyRing.splitUserId(userId);
|
|
|
|
// TODO: comment field?
|
|
|
|
if (userIdSplit.name != null) {
|
|
if (userIdSplit.email != null) {
|
|
if (!mMergedUserIds.containsKey(userIdSplit.name)) {
|
|
HashSet<String> emails = new HashSet<>();
|
|
emails.add(userIdSplit.email);
|
|
mMergedUserIds.put(userIdSplit.name, emails);
|
|
} else {
|
|
mMergedUserIds.get(userIdSplit.name).add(userIdSplit.email);
|
|
}
|
|
} else {
|
|
// name only
|
|
mMergedUserIds.put(userIdSplit.name, new HashSet<String>());
|
|
}
|
|
} else {
|
|
// fallback
|
|
mMergedUserIds.put(userId, new HashSet<String>());
|
|
}
|
|
}
|
|
|
|
mSortedUserIds = null;
|
|
}
|
|
|
|
private void sortMergedUserIds() {
|
|
mSortedUserIds = new ArrayList<>(mMergedUserIds.entrySet());
|
|
|
|
Collections.sort(mSortedUserIds,
|
|
(entry1, entry2) -> entry1.getKey().compareTo(entry2.getKey()));
|
|
}
|
|
|
|
@Override
|
|
public void writeToParcel(Parcel dest, int flags) {
|
|
dest.writeParcelable(mParcelableKeyRing, flags);
|
|
dest.writeSerializable(mPrimaryUserId);
|
|
dest.writeStringList(mUserIds);
|
|
dest.writeSerializable(mMergedUserIds);
|
|
dest.writeByte((byte) (mRevoked ? 1 : 0));
|
|
dest.writeByte((byte) (mExpired ? 1 : 0));
|
|
dest.writeByte((byte) (mUpdated ? 1 : 0));
|
|
dest.writeInt(mDate == null ? 0 : 1);
|
|
if (mDate != null) {
|
|
dest.writeLong(mDate.getTime());
|
|
}
|
|
dest.writeByteArray(mFingerprint);
|
|
dest.writeString(mKeyIdHex);
|
|
dest.writeInt(mBitStrength == null ? 0 : 1);
|
|
if (mBitStrength != null) {
|
|
dest.writeInt(mBitStrength);
|
|
}
|
|
dest.writeString(mAlgorithm);
|
|
dest.writeByte((byte) (mSecretKey ? 1 : 0));
|
|
dest.writeParcelable(mKeyserver, flags);
|
|
dest.writeString(mFbUsername);
|
|
}
|
|
|
|
public static final Creator<ImportKeysListEntry> CREATOR = new Creator<ImportKeysListEntry>() {
|
|
public ImportKeysListEntry createFromParcel(final Parcel source) {
|
|
ImportKeysListEntry vr = new ImportKeysListEntry();
|
|
|
|
vr.mParcelableKeyRing = source.readParcelable(ParcelableKeyRing.class.getClassLoader());
|
|
vr.mPrimaryUserId = (UserId) source.readSerializable();
|
|
vr.mUserIds = new ArrayList<>();
|
|
source.readStringList(vr.mUserIds);
|
|
vr.mMergedUserIds = (HashMap<String, HashSet<String>>) source.readSerializable();
|
|
vr.mRevoked = source.readByte() == 1;
|
|
vr.mExpired = source.readByte() == 1;
|
|
vr.mUpdated = source.readByte() == 1;
|
|
vr.mDate = source.readInt() != 0 ? new Date(source.readLong()) : null;
|
|
vr.mFingerprint = source.createByteArray();
|
|
vr.mKeyIdHex = source.readString();
|
|
vr.mBitStrength = source.readInt() != 0 ? source.readInt() : null;
|
|
vr.mAlgorithm = source.readString();
|
|
vr.mSecretKey = source.readByte() == 1;
|
|
vr.mKeyserver = source.readParcelable(HkpKeyserverAddress.class.getClassLoader());
|
|
vr.mFbUsername = source.readString();
|
|
|
|
return vr;
|
|
}
|
|
|
|
public ImportKeysListEntry[] newArray(final int size) {
|
|
return new ImportKeysListEntry[size];
|
|
}
|
|
};
|
|
|
|
public int describeContents() {
|
|
return 0;
|
|
}
|
|
|
|
}
|