Merge pull request #2329 from wiktor-k/wkd-url
Extend WKD support to include WKD URLs
This commit is contained in:
commit
1e05b7999e
|
@ -719,6 +719,42 @@
|
|||
<data android:pathPattern="/..*/publickey/download" />
|
||||
</intent-filter>
|
||||
|
||||
<!-- VIEW from Web Key Directory urls opened in a browser/Chrome -->
|
||||
<intent-filter android:label="@string/intent_import_key">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
|
||||
<!-- if we don't specify a host, pathPattern will be ignored-->
|
||||
<data android:host="*" />
|
||||
|
||||
<data android:pathPattern="/.well-known/openpgpkey/hu/.*" />
|
||||
|
||||
<!-- Chrome/Built-in browser will not be triggered if there is mimeType -->
|
||||
</intent-filter>
|
||||
|
||||
<!-- VIEW from Web Key Directory urls opened in Firefox for Android -->
|
||||
<intent-filter android:label="@string/intent_import_key">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
||||
<data android:scheme="https" />
|
||||
|
||||
<!-- if we don't specify a host, pathPattern will be ignored-->
|
||||
<data android:host="*" />
|
||||
|
||||
<data android:pathPattern="/.well-known/openpgpkey/hu/.*" />
|
||||
|
||||
<!-- Firefox for Android requires mimeType -->
|
||||
<data android:mimeType="application/octet-stream" />
|
||||
<data android:mimeType="application/pgp-keys" />
|
||||
</intent-filter>
|
||||
|
||||
<!-- IMPORT_KEY with files TODO: does this work? -->
|
||||
<intent-filter android:label="@string/intent_import_key">
|
||||
<action android:name="org.sufficientlysecure.keychain.action.IMPORT_KEY" />
|
||||
|
|
|
@ -126,6 +126,7 @@ public final class Constants {
|
|||
public static final String CACHED_CONSOLIDATE = "cachedConsolidate";
|
||||
public static final String SEARCH_KEYSERVER = "search_keyserver_pref";
|
||||
public static final String SEARCH_KEYBASE = "search_keybase_pref";
|
||||
public static final String SEARCH_WEB_KEY_DIRECTORY = "search_wkd_pref";
|
||||
public static final String USE_NUMKEYPAD_FOR_SECURITY_TOKEN_PIN = "useNumKeypadForYubikeyPin";
|
||||
public static final String ENCRYPT_FILENAMES = "encryptFilenames";
|
||||
public static final String FILE_USE_COMPRESSION = "useFileCompression";
|
||||
|
|
|
@ -42,16 +42,16 @@ public class CloudSearch {
|
|||
// it's a Vector for sync, multiple threads might report problems
|
||||
final Vector<KeyserverClient.CloudSearchFailureException> problems = new Vector<>();
|
||||
|
||||
if (cloudPrefs.searchKeyserver) {
|
||||
servers.add(HkpKeyserverClient.fromHkpKeyserverAddress(cloudPrefs.keyserver));
|
||||
if (cloudPrefs.isKeyserverEnabled()) {
|
||||
servers.add(HkpKeyserverClient.fromHkpKeyserverAddress(cloudPrefs.getKeyserver()));
|
||||
}
|
||||
if (cloudPrefs.searchKeybase) {
|
||||
if (cloudPrefs.isKeybaseEnabled()) {
|
||||
servers.add(KeybaseKeyserverClient.getInstance());
|
||||
}
|
||||
if (cloudPrefs.searchFacebook) {
|
||||
if (cloudPrefs.isFacebookEnabled()) {
|
||||
servers.add(FacebookKeyserverClient.getInstance());
|
||||
}
|
||||
if (cloudPrefs.searchWebKeyDirectory) {
|
||||
if (cloudPrefs.isWebKeyDirectoryEnabled()) {
|
||||
servers.add(WebKeyDirectoryClient.getInstance());
|
||||
}
|
||||
|
||||
|
|
|
@ -19,30 +19,23 @@ package org.sufficientlysecure.keychain.keyimport;
|
|||
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import org.sufficientlysecure.keychain.network.OkHttpClientFactory;
|
||||
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.util.ParcelableProxy;
|
||||
import org.sufficientlysecure.keychain.util.ZBase32;
|
||||
import org.sufficientlysecure.keychain.util.WebKeyDirectoryUtil;
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.Proxy;
|
||||
import java.net.URL;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import timber.log.Timber;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -59,12 +52,10 @@ public class WebKeyDirectoryClient implements KeyserverClient {
|
|||
private WebKeyDirectoryClient() {
|
||||
}
|
||||
|
||||
private static final Pattern EMAIL_PATTERN = Pattern.compile("^\\s*(.+)@(.+)\\s*$");
|
||||
|
||||
@Override
|
||||
public List<ImportKeysListEntry> search(String name, ParcelableProxy proxy)
|
||||
throws QueryFailedException {
|
||||
URL webKeyDirectoryURL = toWebKeyDirectoryURL(name);
|
||||
URL webKeyDirectoryURL = WebKeyDirectoryUtil.toWebKeyDirectoryURL(name);
|
||||
|
||||
if (webKeyDirectoryURL == null) {
|
||||
Timber.d("Name not supported by Web Key Directory Client: " + name);
|
||||
|
@ -103,7 +94,7 @@ public class WebKeyDirectoryClient implements KeyserverClient {
|
|||
|
||||
Request request = new Request.Builder().url(url).build();
|
||||
|
||||
OkHttpClient client = OkHttpClientFactory.getClientPinnedIfAvailable(url, proxy);
|
||||
OkHttpClient client = OkHttpClientFactory.getClientPinnedIfAvailableWithRedirects(url, proxy);
|
||||
Response response = client.newCall(request).execute();
|
||||
|
||||
if (response.isSuccessful()) {
|
||||
|
@ -130,31 +121,4 @@ public class WebKeyDirectoryClient implements KeyserverClient {
|
|||
public void add(String armoredKey, ParcelableProxy proxy) {
|
||||
throw new UnsupportedOperationException("Uploading keys to Web Key Directory is not supported");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static URL toWebKeyDirectoryURL(String name) {
|
||||
Matcher matcher = EMAIL_PATTERN.matcher(name);
|
||||
|
||||
if (!matcher.matches()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String localPart = matcher.group(1);
|
||||
String encodedPart = ZBase32.encode(toSHA1(localPart.toLowerCase().getBytes()));
|
||||
String domain = matcher.group(2);
|
||||
|
||||
try {
|
||||
return new URL("https://" + domain + "/.well-known/openpgpkey/hu/" + encodedPart);
|
||||
} catch (MalformedURLException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] toSHA1(byte[] input) {
|
||||
try {
|
||||
return MessageDigest.getInstance("SHA-1").digest(input);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new AssertionError("SHA-1 should always be available");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,10 +47,18 @@ public class OkHttpClientFactory {
|
|||
}
|
||||
|
||||
public static OkHttpClient getClientPinnedIfAvailable(URL url, Proxy proxy) {
|
||||
// don't follow any redirects for keyservers, as discussed in the security audit
|
||||
return getClientPinnedIfAvailable(url, proxy, false);
|
||||
}
|
||||
|
||||
public static OkHttpClient getClientPinnedIfAvailableWithRedirects(URL url, Proxy proxy) {
|
||||
return getClientPinnedIfAvailable(url, proxy, true);
|
||||
}
|
||||
|
||||
private static OkHttpClient getClientPinnedIfAvailable(URL url, Proxy proxy, boolean followRedirects) {
|
||||
OkHttpClient.Builder builder = new OkHttpClient.Builder();
|
||||
|
||||
// don't follow any redirects for keyservers, as discussed in the security audit
|
||||
builder.followRedirects(false)
|
||||
builder.followRedirects(followRedirects)
|
||||
.followSslRedirects(false);
|
||||
|
||||
if (proxy != null) {
|
||||
|
|
|
@ -57,6 +57,8 @@ public class ImportKeysActivity extends BaseActivity implements ImportKeysListen
|
|||
public static final String ACTION_IMPORT_KEY_FROM_KEYSERVER = Constants.IMPORT_KEY_FROM_KEYSERVER;
|
||||
public static final String ACTION_IMPORT_KEY_FROM_FACEBOOK
|
||||
= Constants.INTENT_PREFIX + "IMPORT_KEY_FROM_FACEBOOK";
|
||||
public static final String ACTION_IMPORT_KEY_FROM_WEB_KEY_DIRECTORY
|
||||
= Constants.INTENT_PREFIX + "ACTION_IMPORT_KEY_FROM_WEB_KEY_DIRECTORY";
|
||||
public static final String ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT =
|
||||
Constants.INTENT_PREFIX + "IMPORT_KEY_FROM_KEY_SERVER_AND_RETURN_RESULT";
|
||||
public static final String ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN = Constants.INTENT_PREFIX
|
||||
|
@ -122,6 +124,8 @@ public class ImportKeysActivity extends BaseActivity implements ImportKeysListen
|
|||
if (Intent.ACTION_VIEW.equals(action)) {
|
||||
if (FacebookKeyserverClient.isFacebookHost(dataUri)) {
|
||||
action = ACTION_IMPORT_KEY_FROM_FACEBOOK;
|
||||
} else if ("https".equalsIgnoreCase(scheme) || dataUri.getPath().startsWith("/.well-known/openpgpkey/hu/")) {
|
||||
action = ACTION_IMPORT_KEY_FROM_WEB_KEY_DIRECTORY;
|
||||
} else if ("http".equalsIgnoreCase(scheme) || "https".equalsIgnoreCase(scheme)) {
|
||||
action = ACTION_SEARCH_KEYSERVER_FROM_URL;
|
||||
} else if (Constants.FINGERPRINT_SCHEME.equalsIgnoreCase(scheme)) {
|
||||
|
@ -208,17 +212,23 @@ public class ImportKeysActivity extends BaseActivity implements ImportKeysListen
|
|||
String fbUsername = FacebookKeyserverClient.getUsernameFromUri(dataUri);
|
||||
|
||||
Preferences.CloudSearchPrefs cloudSearchPrefs =
|
||||
new Preferences.CloudSearchPrefs(false, true, true, false, null);
|
||||
Preferences.CloudSearchPrefs.createSocialOnly();
|
||||
// search immediately
|
||||
startListFragment(null, null, fbUsername, cloudSearchPrefs);
|
||||
break;
|
||||
}
|
||||
case ACTION_IMPORT_KEY_FROM_WEB_KEY_DIRECTORY: {
|
||||
Preferences.CloudSearchPrefs cloudSearchPrefs =
|
||||
Preferences.CloudSearchPrefs.createWebKeyDirectoryOnly();
|
||||
// search immediately
|
||||
startListFragment(null, null, dataUri.toString(), cloudSearchPrefs);
|
||||
break;
|
||||
}
|
||||
case ACTION_SEARCH_KEYSERVER_FROM_URL: {
|
||||
// get keyserver from URL
|
||||
HkpKeyserverAddress keyserver = HkpKeyserverAddress.createFromUri(
|
||||
dataUri.getScheme() + "://" + dataUri.getAuthority());
|
||||
Preferences.CloudSearchPrefs cloudSearchPrefs = new Preferences.CloudSearchPrefs(
|
||||
true, false, false, false, keyserver);
|
||||
Preferences.CloudSearchPrefs cloudSearchPrefs = Preferences.CloudSearchPrefs.createKeyserverOnly(keyserver);
|
||||
Timber.d("Using keyserver: " + keyserver);
|
||||
|
||||
// process URL to get operation and query
|
||||
|
|
|
@ -18,28 +18,27 @@
|
|||
package org.sufficientlysecure.keychain.util;
|
||||
|
||||
|
||||
import java.net.Proxy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.ListIterator;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.Editor;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
import com.google.auto.value.AutoValue;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Constants.Pref;
|
||||
import org.sufficientlysecure.keychain.KeychainApplication;
|
||||
import org.sufficientlysecure.keychain.keyimport.HkpKeyserverAddress;
|
||||
import org.sufficientlysecure.keychain.service.KeyserverSyncAdapterService;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
import java.net.Proxy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.ListIterator;
|
||||
|
||||
|
||||
/**
|
||||
* Singleton Implementation of a Preference Helper
|
||||
|
@ -345,10 +344,10 @@ public class Preferences {
|
|||
// cloud prefs
|
||||
|
||||
public CloudSearchPrefs getCloudSearchPrefs() {
|
||||
return new CloudSearchPrefs(mSharedPreferences.getBoolean(Pref.SEARCH_KEYSERVER, true),
|
||||
return CloudSearchPrefs.create(mSharedPreferences.getBoolean(Pref.SEARCH_KEYSERVER, true),
|
||||
mSharedPreferences.getBoolean(Pref.SEARCH_KEYBASE, true),
|
||||
false,
|
||||
true,
|
||||
mSharedPreferences.getBoolean(Pref.SEARCH_WEB_KEY_DIRECTORY, true),
|
||||
getPreferredKeyserver());
|
||||
}
|
||||
|
||||
|
@ -362,62 +361,44 @@ public class Preferences {
|
|||
editor.commit();
|
||||
}
|
||||
|
||||
public static class CloudSearchPrefs implements Parcelable {
|
||||
public final boolean searchKeyserver;
|
||||
public final boolean searchKeybase;
|
||||
public final boolean searchFacebook;
|
||||
public final boolean searchWebKeyDirectory;
|
||||
public final HkpKeyserverAddress keyserver;
|
||||
@AutoValue
|
||||
public static abstract class CloudSearchPrefs implements Parcelable {
|
||||
public abstract boolean isKeyserverEnabled();
|
||||
public abstract boolean isKeybaseEnabled();
|
||||
public abstract boolean isFacebookEnabled();
|
||||
public abstract boolean isWebKeyDirectoryEnabled();
|
||||
|
||||
@Nullable
|
||||
public abstract HkpKeyserverAddress getKeyserver();
|
||||
|
||||
/**
|
||||
* @param searchKeyserver should passed keyserver be searched
|
||||
* @param searchKeybase should keybase.io be searched
|
||||
* @param keyserver the keyserver url authority to search on
|
||||
* @param searchKeyserver should passed keyserver be searched
|
||||
* @param searchKeybase should keybase.io be searched
|
||||
* @param searchFacebook should Facebook be searched
|
||||
* @param searchWebKeyDirectory should WKD be searched
|
||||
* @param keyserver the keyserver url authority to search on
|
||||
*/
|
||||
public CloudSearchPrefs(boolean searchKeyserver, boolean searchKeybase,
|
||||
boolean searchFacebook, boolean searchWebKeyDirectory,
|
||||
HkpKeyserverAddress keyserver) {
|
||||
this.searchKeyserver = searchKeyserver;
|
||||
this.searchKeybase = searchKeybase;
|
||||
this.searchFacebook = searchFacebook;
|
||||
this.searchWebKeyDirectory = searchWebKeyDirectory;
|
||||
this.keyserver = keyserver;
|
||||
public static CloudSearchPrefs create(boolean searchKeyserver, boolean searchKeybase,
|
||||
boolean searchFacebook, boolean searchWebKeyDirectory,
|
||||
@Nullable HkpKeyserverAddress keyserver) {
|
||||
return new AutoValue_Preferences_CloudSearchPrefs(searchKeyserver,
|
||||
searchKeybase,
|
||||
searchFacebook,
|
||||
searchWebKeyDirectory,
|
||||
keyserver);
|
||||
}
|
||||
|
||||
protected CloudSearchPrefs(Parcel in) {
|
||||
searchKeyserver = in.readByte() != 0x00;
|
||||
searchKeybase = in.readByte() != 0x00;
|
||||
searchFacebook = in.readByte() != 0x00;
|
||||
searchWebKeyDirectory = in.readByte() != 0x00;
|
||||
keyserver = in.readParcelable(HkpKeyserverAddress.class.getClassLoader());
|
||||
public static CloudSearchPrefs createWebKeyDirectoryOnly() {
|
||||
return create(false, false, false, true, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
public static CloudSearchPrefs createKeyserverOnly(HkpKeyserverAddress keyserver) {
|
||||
return create(true, false, false, false, keyserver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeByte((byte) (searchKeyserver ? 0x01 : 0x00));
|
||||
dest.writeByte((byte) (searchKeybase ? 0x01 : 0x00));
|
||||
dest.writeByte((byte) (searchFacebook ? 0x01 : 0x00));
|
||||
dest.writeByte((byte) (searchWebKeyDirectory ? 0x01 : 0x00));
|
||||
dest.writeParcelable(keyserver, flags);
|
||||
public static CloudSearchPrefs createSocialOnly() {
|
||||
return create(false, true, true, false, null);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<CloudSearchPrefs> CREATOR
|
||||
= new Parcelable.Creator<CloudSearchPrefs>() {
|
||||
@Override
|
||||
public CloudSearchPrefs createFromParcel(Parcel in) {
|
||||
return new CloudSearchPrefs(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CloudSearchPrefs[] newArray(int size) {
|
||||
return new CloudSearchPrefs[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// sync preferences
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
package org.sufficientlysecure.keychain.util;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class WebKeyDirectoryUtil {
|
||||
|
||||
private static final Pattern EMAIL_PATTERN = Pattern.compile("^\\s*([^\\s]+)@([^\\s]+)\\s*$");
|
||||
|
||||
private WebKeyDirectoryUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to construct a Web Key Directory from a given name.
|
||||
* Returns {@code null} if unsuccessful.
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/draft-koch-openpgp-webkey-service-05#section-3.1">Key Discovery</a>
|
||||
*/
|
||||
@Nullable
|
||||
public static URL toWebKeyDirectoryURL(String name) {
|
||||
if (name == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (name.startsWith("https://") && name.contains("/.well-known/openpgpkey/hu/")) {
|
||||
try {
|
||||
return new URL(name);
|
||||
} catch (MalformedURLException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Matcher matcher = EMAIL_PATTERN.matcher(name);
|
||||
|
||||
if (!matcher.matches()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String localPart = matcher.group(1);
|
||||
String encodedPart = ZBase32.encode(toSHA1(localPart.toLowerCase().getBytes()));
|
||||
String domain = matcher.group(2);
|
||||
|
||||
try {
|
||||
return new URL("https://" + domain + "/.well-known/openpgpkey/hu/" + encodedPart);
|
||||
} catch (MalformedURLException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] toSHA1(byte[] input) {
|
||||
try {
|
||||
return MessageDigest.getInstance("SHA-1").digest(input);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new AssertionError("SHA-1 should always be available");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -211,6 +211,8 @@
|
|||
<string name="pref_keybase_summary">"Search keys on keybase.io"</string>
|
||||
<string name="pref_facebook">"Facebook"</string>
|
||||
<string name="pref_facebook_summary">"Search keys on Facebook by username"</string>
|
||||
<string name="pref_wkd">"Web Key Directory"</string>
|
||||
<string name="pref_wkd_summary">"Search keys using Web Key Directory"</string>
|
||||
|
||||
<string name="label_sync_settings_keyserver_title">"Automatic key updates"</string>
|
||||
<string name="label_sync_settings_keyserver_summary_on">"Every three days, keys are updated from the preferred keyserver"</string>
|
||||
|
|
|
@ -14,4 +14,9 @@
|
|||
android:key="search_keybase_pref"
|
||||
android:summary="@string/pref_keybase_summary"
|
||||
android:title="@string/pref_keybase" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="search_wkd_pref"
|
||||
android:summary="@string/pref_wkd_summary"
|
||||
android:title="@string/pref_wkd" />
|
||||
</PreferenceScreen>
|
|
@ -0,0 +1,39 @@
|
|||
package org.sufficientlysecure.keychain.util;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
|
||||
public class WebKeyDirectoryUtilTest {
|
||||
|
||||
@Test
|
||||
public void testWkd() {
|
||||
URL url = WebKeyDirectoryUtil.toWebKeyDirectoryURL("test-wkd@openkeychain.org");
|
||||
assertNotNull(url);
|
||||
assertEquals("openkeychain.org", url.getHost());
|
||||
assertEquals("https", url.getProtocol());
|
||||
assertEquals("/.well-known/openpgpkey/hu/4hg7tescnttreaouu4z1izeuuyibwww1", url.getPath());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWkdWithSpaces() {
|
||||
URL url = WebKeyDirectoryUtil.toWebKeyDirectoryURL(" test-wkd@openkeychain.org ");
|
||||
assertNotNull(url);
|
||||
assertEquals("openkeychain.org", url.getHost());
|
||||
assertEquals("https", url.getProtocol());
|
||||
assertEquals("/.well-known/openpgpkey/hu/4hg7tescnttreaouu4z1izeuuyibwww1", url.getPath());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWkdDirectUrl() {
|
||||
URL url = WebKeyDirectoryUtil.toWebKeyDirectoryURL("https://openkeychain.org/.well-known/openpgpkey/hu/4hg7tescnttreaouu4z1izeuuyibwww1");
|
||||
assertNotNull(url);
|
||||
assertEquals("openkeychain.org", url.getHost());
|
||||
assertEquals("https", url.getProtocol());
|
||||
assertEquals("/.well-known/openpgpkey/hu/4hg7tescnttreaouu4z1izeuuyibwww1", url.getPath());
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue