diff options
| author | StevenWdV <stevenwdv@gmail.com> | 2022-01-24 14:59:25 +0100 |
|---|---|---|
| committer | StevenWdV <stevenwdv@gmail.com> | 2022-01-24 16:24:57 +0100 |
| commit | e544c6fa9e15e7277da79e2464243e90b2706b8c (patch) | |
| tree | de6613747e0e34a799089d4677f9833a85748712 | |
| parent | aab2e4b966c82b67eb0e204060e5ea6cd4ea15cf (diff) | |
Cleanup
Added variables to Makefiles to specify custom exports/ directory;
Split exception classes in Java & C#;
Added more comments;
Renamed library and Go package;
Removed real (pure) tests;
Added generate_lib.ps1 to generate import .lib for Windows (Swift);
Moved built Go libraries to exports/lib/;
Switch to hopefully faster Swift GitHub Action.
| -rw-r--r-- | .gitattributes | 3 | ||||
| -rw-r--r-- | .github/workflows/test.yml | 4 | ||||
| -rw-r--r-- | Makefile | 7 | ||||
| -rw-r--r-- | README.md | 47 | ||||
| -rw-r--r-- | exports/.gitignore | 2 | ||||
| -rw-r--r-- | exports/Makefile | 21 | ||||
| -rw-r--r-- | exports/exports.go | 13 | ||||
| -rw-r--r-- | exports/generate_lib.ps1 | 30 | ||||
| -rw-r--r-- | exports/platform.mk | 13 | ||||
| -rw-r--r-- | test_data/empty (renamed from test_data/dummy/empty) | 0 | ||||
| -rw-r--r--[-rwxr-xr-x] | test_data/generate.sh (renamed from test_data/dummy/generate.sh) | 6 | ||||
| -rw-r--r--[-rwxr-xr-x] | test_data/generate_forged.py (renamed from test_data/dummy/generate_forged.py) | 2 | ||||
| -rw-r--r-- | test_data/organization_list.json (renamed from test_data/dummy/organization_list.json) | 0 | ||||
| -rw-r--r-- | test_data/organization_list.json.minisig (renamed from test_data/dummy/organization_list.json.minisig) | 0 | ||||
| -rw-r--r-- | test_data/organization_list.json.tc_servlist.minisig (renamed from test_data/dummy/organization_list.json.tc_servlist.minisig) | 0 | ||||
| -rw-r--r-- | test_data/other_list.json (renamed from test_data/dummy/other_list.json) | 0 | ||||
| -rw-r--r-- | test_data/other_list.json.minisig (renamed from test_data/dummy/other_list.json.minisig) | 0 | ||||
| -rw-r--r-- | test_data/public.key (renamed from test_data/dummy/public.key) | 0 | ||||
| -rw-r--r-- | test_data/random.txt (renamed from test_data/dummy/random.txt) | 0 | ||||
| -rw-r--r-- | test_data/real/organization_list-1.json | 1 | ||||
| -rw-r--r-- | test_data/real/organization_list-1.json.pure.minisig | 4 | ||||
| -rw-r--r-- | test_data/real/server_list-1.json | 1 | ||||
| -rw-r--r-- | test_data/real/server_list-1.json.pure.minisig | 4 | ||||
| -rw-r--r-- | test_data/secret.key (renamed from test_data/dummy/secret.key) | 0 | ||||
| -rw-r--r-- | test_data/server_list.json (renamed from test_data/dummy/server_list.json) | 0 | ||||
| -rw-r--r-- | test_data/server_list.json.blake2b (renamed from test_data/dummy/server_list.json.blake2b) | bin | 64 -> 64 bytes | |||
| -rw-r--r-- | test_data/server_list.json.forged_keyid.minisig (renamed from test_data/dummy/server_list.json.forged_keyid.minisig) | 0 | ||||
| -rw-r--r-- | test_data/server_list.json.forged_pure.minisig (renamed from test_data/dummy/server_list.json.forged_pure.minisig) | 0 | ||||
| -rw-r--r-- | test_data/server_list.json.large_time.minisig (renamed from test_data/dummy/server_list.json.large_time.minisig) | 0 | ||||
| -rw-r--r-- | test_data/server_list.json.minisig (renamed from test_data/dummy/server_list.json.minisig) | 0 | ||||
| -rw-r--r-- | test_data/server_list.json.pure.minisig (renamed from test_data/dummy/server_list.json.pure.minisig) | 0 | ||||
| -rw-r--r-- | test_data/server_list.json.tc_earliertime.minisig (renamed from test_data/dummy/server_list.json.tc_earliertime.minisig) | 0 | ||||
| -rw-r--r-- | test_data/server_list.json.tc_emptyfile.minisig (renamed from test_data/dummy/server_list.json.tc_emptyfile.minisig) | 0 | ||||
| -rw-r--r-- | test_data/server_list.json.tc_emptytime.minisig (renamed from test_data/dummy/server_list.json.tc_emptytime.minisig) | 0 | ||||
| -rw-r--r-- | test_data/server_list.json.tc_latertime.minisig (renamed from test_data/dummy/server_list.json.tc_latertime.minisig) | 0 | ||||
| -rw-r--r-- | test_data/server_list.json.tc_nofile.minisig (renamed from test_data/dummy/server_list.json.tc_nofile.minisig) | 0 | ||||
| -rw-r--r-- | test_data/server_list.json.tc_nohashed.minisig (renamed from test_data/dummy/server_list.json.tc_nohashed.minisig) | 0 | ||||
| -rw-r--r-- | test_data/server_list.json.tc_notime.minisig (renamed from test_data/dummy/server_list.json.tc_notime.minisig) | 0 | ||||
| -rw-r--r-- | test_data/server_list.json.tc_orglist.minisig (renamed from test_data/dummy/server_list.json.tc_orglist.minisig) | 0 | ||||
| -rw-r--r-- | test_data/server_list.json.tc_otherfile.minisig (renamed from test_data/dummy/server_list.json.tc_otherfile.minisig) | 0 | ||||
| -rw-r--r-- | test_data/server_list.json.tc_random.minisig (renamed from test_data/dummy/server_list.json.tc_random.minisig) | 0 | ||||
| -rw-r--r-- | test_data/server_list.json.wrong_key.minisig (renamed from test_data/dummy/server_list.json.wrong_key.minisig) | 0 | ||||
| -rw-r--r-- | test_data/wrong_public.key (renamed from test_data/dummy/wrong_public.key) | 0 | ||||
| -rw-r--r-- | test_data/wrong_secret.key (renamed from test_data/dummy/wrong_secret.key) | 0 | ||||
| -rw-r--r-- | verify.go | 50 | ||||
| -rw-r--r-- | verify_test.go | 146 | ||||
| -rw-r--r-- | wrappers/csharp/Discovery.cs | 86 | ||||
| -rw-r--r-- | wrappers/csharp/EduVpnCommon.csproj | 57 | ||||
| -rw-r--r-- | wrappers/csharp/EduVpnCommon.props | 7 | ||||
| -rw-r--r-- | wrappers/csharp/EduVpnCommonTests/VerifyTests.cs | 27 | ||||
| -rw-r--r-- | wrappers/csharp/Makefile | 10 | ||||
| -rw-r--r-- | wrappers/csharp/README.md | 15 | ||||
| -rw-r--r-- | wrappers/java/Makefile | 15 | ||||
| -rw-r--r-- | wrappers/java/README.md | 2 | ||||
| -rw-r--r-- | wrappers/java/pom.xml | 24 | ||||
| -rw-r--r-- | wrappers/java/src/main/java/nl/eduvpn/common/Discovery.java | 47 | ||||
| -rw-r--r-- | wrappers/java/src/main/java/nl/eduvpn/common/InvalidSignatureException.java | 8 | ||||
| -rw-r--r-- | wrappers/java/src/main/java/nl/eduvpn/common/InvalidSignatureUnknownKeyException.java | 8 | ||||
| -rw-r--r-- | wrappers/java/src/main/java/nl/eduvpn/common/SignatureTooOldException.java | 8 | ||||
| -rw-r--r-- | wrappers/java/src/main/java/nl/eduvpn/common/UnknownVerifyException.java | 9 | ||||
| -rw-r--r-- | wrappers/java/src/main/java/nl/eduvpn/common/VerifyException.java | 11 | ||||
| -rw-r--r-- | wrappers/java/src/test/java/nl/eduvpn/common/VerifyTests.java | 37 | ||||
| -rw-r--r-- | wrappers/php/.gitignore | 1 | ||||
| -rw-r--r-- | wrappers/php/Makefile | 38 | ||||
| -rw-r--r-- | wrappers/php/README.md | 6 | ||||
| -rw-r--r-- | wrappers/php/src/Discovery.php | 10 | ||||
| -rw-r--r-- | wrappers/php/src/SignatureTooOldException.php | 2 | ||||
| -rw-r--r-- | wrappers/php/tests/DiscoveryTest.php | 22 | ||||
| -rw-r--r-- | wrappers/python/Makefile | 16 | ||||
| -rw-r--r-- | wrappers/python/README.md | 15 | ||||
| -rw-r--r-- | wrappers/python/eduvpncommon/discovery.py | 31 | ||||
| -rwxr-xr-x | wrappers/python/setup.py | 25 | ||||
| -rwxr-xr-x | wrappers/python/test_discovery.py | 26 | ||||
| -rw-r--r-- | wrappers/swift/CEduVpnCommon/Sources/CEduVpnCommon/module.modulemap | 4 | ||||
| -rw-r--r-- | wrappers/swift/Makefile | 33 | ||||
| -rw-r--r-- | wrappers/swift/README.md | 20 | ||||
| -rw-r--r-- | wrappers/swift/Sources/EduVpnCommon/EduVpnCommon.swift | 8 | ||||
| -rw-r--r-- | wrappers/swift/Tests/EduVpnCommonTests/EduVpnCommonTests.swift | 22 | ||||
| -rwxr-xr-x | wrappers/swift/swift.cmd | 2 |
79 files changed, 610 insertions, 396 deletions
diff --git a/.gitattributes b/.gitattributes index d6ceb16..eaa896f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,5 @@ +# Interpret .json & .blake2b test data files as binary (not text) +# Otherwise test signatures made with different line endings will become invalid +# Use LF for created .json files, also on Windows test_data/**/*.json -text eol=lf test_data/**/*.blake2b -text diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index df83b6f..f405945 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -30,7 +30,7 @@ jobs: with: distribution: temurin java-version: 11 - - uses: fwal/setup-swift@v1 + - uses: slashmo/install-swift@v0.1.0 with: - swift-version: 5 + version: 5.5 - run: make test-wrappers @@ -14,17 +14,18 @@ wrappers = $(wildcard wrappers/*/) test-wrappers: build $(MAKE) $(foreach wrapper,$(wrappers),.test_$(wrapper)) +# Enable parallelism if -j is specified clean: $(MAKE) .clean_libs $(foreach wrapper,$(wrappers),.clean_$(wrapper)) .clean_libs: $(MAKE) -C exports clean +# Define test & clean for each wrapper define wrapper_targets .test_$(1): - $(MAKE) -C $(1) test + $(MAKE) -C "$(1)" test .clean_$(1): - $(MAKE) -C $(1) clean + $(MAKE) -C "$(1)" clean endef - $(foreach wrapper,$(wrappers),$(eval $(call wrapper_targets,$(wrapper)))) @@ -3,7 +3,7 @@ This repository contains a Go library with functions that all EduVPN clients can use. The goal is to let EduVPN clients link against this library and gradually merge more common logic between EduVPN clients into this repository. -cgo is used to build the go library into a shared dynamic library. Wrappers will be written using some FFI framework for +cgo is used to build the Go library into a shared dynamic library. Wrappers will be written using some FFI framework for each language used in EduVPN clients to easily interface with the library. ## Functionality @@ -15,7 +15,7 @@ be downloaded by the caller. To run the Go tests, you will need [Go](https://go.dev/doc/install) 1.15 or later (add it to your `PATH`). To build the shared library, you will additionally need to install gcc. If you want to use the Makefile scripts you will need GNU -make. +make (not bsd make). On Windows, you can install gcc and make (or even Go) via MinGW or Cygwin or use WSL. For MinGW: @@ -25,15 +25,16 @@ On Windows, you can install gcc and make (or even Go) via MinGW or Cygwin or use e.g. [`mingw-w64-x86_64-make`](https://packages.msys2.org/package/mingw-w64-x86_64-make?repo=mingw64) and use `mingw32-make` in the command line) 3. To compile for x86_64: - 1. Install the [`mingw-w64-x86_64-gcc`](https://packages.msys2.org/package/mingw-w64-x86_64-gcc?repo=mingw64) package - 2. Open the MinGW 64-bit console, via the start menu, or in your current - terminal: `path/to/msys64/msys2_shell.cmd -mingw64 -defterm -no-start -use-full-path` - 3. Run the make commands in the project directory + 1. Install the [`mingw-w64-x86_64-gcc`](https://packages.msys2.org/package/mingw-w64-x86_64-gcc?repo=mingw64) + package + 2. Open the MinGW 64-bit console, via the start menu, or in your current + terminal: `path/to/msys64/msys2_shell.cmd -mingw64 -defterm -no-start -use-full-path` + 3. Run the make commands in the project directory 4. To compile for x86 (32-bit): - 1. Install the [`mingw-w64-i686-gcc`](https://packages.msys2.org/package/mingw-w64-i686-gcc?repo=mingw32) package - 2. Open the MinGW 32-bit console, via the start menu, or in your current - terminal: `path/to/msys64/msys2_shell.cmd -mingw32 -defterm -no-start -use-full-path` - 3. Run the make commands in the project directory + 1. Install the [`mingw-w64-i686-gcc`](https://packages.msys2.org/package/mingw-w64-i686-gcc?repo=mingw32) package + 2. Open the MinGW 32-bit console, via the start menu, or in your current + terminal: `path/to/msys64/msys2_shell.cmd -mingw32 -defterm -no-start -use-full-path` + 3. Run the make commands in the project directory Take a look at `wrappers/<lang>/README.md` for extra instructions for each wrapper. @@ -51,9 +52,15 @@ Build shared library for specified OS & architecture (example): make GOOS=windows GOARCH=386 ``` -Results will be output in `exports/`. +Results will be output in `exports/lib/`. -TODO: notes on cross-compilation +Usually you will need to specify the compiler when cross compiling, for example: + +```shell +make GOOS=windows GOARCH=amd64 CC=x86_64-w64-mingw32-gcc +``` + +For example, you can cross compile for Windows from Linux using [MinGW-w64](https://www.mingw-w64.org/downloads/). Test Go code: @@ -67,9 +74,23 @@ Test wrappers (you will need compilers for all wrappers if you do this): make test-wrappers ``` +Specify `-j` to execute tests in parallel. + +Test both: + +```shell +make test +``` + +Clean built libraries and wrapper builds: + +```shell +make clean -j +``` + Take a look at `wrappers/<lang>/README.md` for descriptions per wrapper. -## Directory +## Structure - `verify.go`: main API - `verify_test.go` and `test_data/`: tests for API diff --git a/exports/.gitignore b/exports/.gitignore index 63ea916..5e5615b 100644 --- a/exports/.gitignore +++ b/exports/.gitignore @@ -1 +1 @@ -/*/ +/lib/* diff --git a/exports/Makefile b/exports/Makefile index 547ee92..67ddc61 100644 --- a/exports/Makefile +++ b/exports/Makefile @@ -2,15 +2,20 @@ include platform.mk -# Creates targets like 'linux/amd64/eduvpn_verify.so' -build: $(GOOS)/$(GOARCH)/$(LIB_PREFIX)eduvpn_verify$(LIB_SUFFIX) +ifeq ($(LIB_SUFFIX),.so) +# Add SONAME as cgo does not currently do this. Mostly for Android, see https://stackoverflow.com/a/48291044 +export CGO_LDFLAGS := $(CGO_LDFLAGS) -Wl,-soname,$(LIB_FILE) +endif -$(GOOS)/$(GOARCH)/$(LIB_PREFIX)eduvpn_verify$(LIB_SUFFIX): exports.go ../verify.go - CGO_ENABLED=1 GOOS=$(GOOS) GOARCH=$(GOARCH) go build -o $@ -buildmode=c-shared $< - mv $(GOOS)/$(GOARCH)/$(LIB_PREFIX)eduvpn_verify.h $(GOOS)/$(GOARCH)/eduvpn_verify.h || true +# Creates targets like 'lib/linux/amd64/libeduvpn_common.so' +build: lib/$(GOOS)/$(GOARCH)/$(LIB_FILE) -copy-to: $(GOOS)/$(GOARCH)/$(LIB_PREFIX)eduvpn_verify$(LIB_SUFFIX) - install $< -Dt "$(COPY_TARGET)" +# Build shared library and remove lib prefix (if any) from header name +# GOOS and GOARCH envvars are set by platform.mk +# This extra target prevents unnecessary rebuild +lib/$(GOOS)/$(GOARCH)/$(LIB_FILE): exports.go ../verify.go + CGO_ENABLED=1 go build -o $@ -buildmode=c-shared $< + mv lib/$(GOOS)/$(GOARCH)/$(LIB_PREFIX)$(LIB_NAME).h lib/$(GOOS)/$(GOARCH)/$(LIB_NAME).h || true # Normalize header name clean: - rm -rf ../exports/*/ + rm -rf ../exports/lib/* diff --git a/exports/exports.go b/exports/exports.go index f841eca..b3d4206 100644 --- a/exports/exports.go +++ b/exports/exports.go @@ -4,25 +4,28 @@ import "C" import "eduvpn-common" -// Functions here should not take string parameters, see https://pkg.go.dev/cmd/cgo#hdr-C_references_to_Go +// Functions here should probably not take string parameters, see https://pkg.go.dev/cmd/cgo#hdr-C_references_to_Go // Verify verifies a signature on a JSON file. See eduvpn_verify.Verify for more details. // It returns 0 for a valid signature and a nonzero eduvpn_verify.VerifyErrorCode otherwise. +// signatureFileContent must be UTF-8-encoded. //export Verify -func Verify(signatureFileContent []byte, signedJson []byte, expectedFileName []byte, minSignTime uint64) int { - valid, err := eduvpn_verify.Verify(string(signatureFileContent), signedJson, string(expectedFileName), minSignTime) +func Verify(signatureFileContent []byte, signedJson []byte, expectedFileName []byte, minSignTime uint64) int8 { + valid, err := eduvpn_discovery.Verify(string(signatureFileContent), signedJson, string(expectedFileName), minSignTime) if valid { return 0 } else { - return int(err.(eduvpn_verify.VerifyError).Code) + return int8(err.(eduvpn_discovery.VerifyError).Code) } } // InsecureTestingSetExtraKey adds an extra allowed key for verification with Verify. // ONLY USE FOR TESTING. Not Thread-safe. Do not call in parallel to Verify. +// keyString must be an ASCII Base64-encoded key. //export InsecureTestingSetExtraKey func InsecureTestingSetExtraKey(keyString []byte) { - eduvpn_verify.InsecureTestingSetExtraKey(string(keyString)) + eduvpn_discovery.InsecureTestingSetExtraKey(string(keyString)) } +// Not used in library, but needed to compile. func main() { panic("compile with -buildmode=c-shared") } diff --git a/exports/generate_lib.ps1 b/exports/generate_lib.ps1 new file mode 100644 index 0000000..ac452ca --- /dev/null +++ b/exports/generate_lib.ps1 @@ -0,0 +1,30 @@ +<# +.SYNOPSIS + Generate .lib import library file for specified .dll file. +.NOTES + Requires dumpbin & lib, may need to execute through VS developer shell. +#> + +param ( + [string]$DllPath +) + +# Compatible with both Windows PowerShell and PowerShell Core + +$ErrorActionPreference = "Stop" + +$dll = Get-Item $DllPath +$def = Join-Path $dll.Directory "$( $dll.BaseName ).def" +$lib = Join-Path $dll.Directory "$( $dll.BaseName ).lib" +$machine = (dumpbin /nologo /headers $dll.FullName | + Select-String -AllMatches 'machine \((.+)\)').Matches[0].Groups[1].Value + +"LIBRARY $( $dll.BaseName )`nEXPORTS`n" + ( +(dumpbin /nologo /exports $dll.FullName | + Select-String -AllMatches '\d+\s+\d+\s+[0-9A-Z]+\s+(\S+)').Matches | + % { $_.Groups[1].Value } | + where { $_[0] -ne '_' } | # Skip _cgo_dummy_export +Out-String) | + Set-Content $def + +lib /machine:$machine /def:"$def" /out:"$lib" diff --git a/exports/platform.mk b/exports/platform.mk index d44c889..cd1248b 100644 --- a/exports/platform.mk +++ b/exports/platform.mk @@ -1,3 +1,5 @@ +# Prevent executing `go env ...` multiple times for the same property +# export is needed for this and also to pass the values on to the Go compiler ifndef GOOS export GOOS != go env GOHOSTOS endif @@ -16,9 +18,16 @@ LIB_PREFIX = lib LIB_SUFFIX = .so endif +# Library name without prefixes/suffixes +LIB_NAME = eduvpn_common +# Library file name +LIB_FILE = $(LIB_PREFIX)$(LIB_NAME)$(LIB_SUFFIX) + +# Get exports/ directory when included from a wrapper exports_dir = $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) +# Add library to dynamic linker path for running tests ifeq (Windows_NT,$(OS)) -export PATH := $(exports_dir)/$(GOOS)/$(GOARCH):$(PATH) +export PATH := $(exports_dir)/lib/$(GOOS)/$(GOARCH):$(PATH) else -export LD_LIBRARY_PATH := $(exports_dir)/$(GOOS)/$(GOARCH):$(LD_LIBRARY_PATH) +export LD_LIBRARY_PATH := $(exports_dir)/lib/$(GOOS)/$(GOARCH):$(LD_LIBRARY_PATH) endif diff --git a/test_data/dummy/empty b/test_data/empty index e69de29..e69de29 100644 --- a/test_data/dummy/empty +++ b/test_data/empty diff --git a/test_data/dummy/generate.sh b/test_data/generate.sh index 2bed447..b1b4545 100755..100644 --- a/test_data/dummy/generate.sh +++ b/test_data/generate.sh @@ -1,10 +1,10 @@ #!/bin/bash # Generate testcases with fake keys -# Make sure we do not delete *.minisigs etc. anywhere -if [ ${PWD##*/} != "dummy" ] +# Make sure we do not delete *.minisigs etc. in the wrong directory +if [ ${PWD##*/} != "test_data" ] then - >&2 echo "Wrong directory, should be run in dummy/" + >&2 echo "Wrong directory, should be run in test_data/" exit 1 fi diff --git a/test_data/dummy/generate_forged.py b/test_data/generate_forged.py index 7832843..843b32d 100755..100644 --- a/test_data/dummy/generate_forged.py +++ b/test_data/generate_forged.py @@ -11,7 +11,7 @@ with open("server_list.json", "rb") as f: with open("server_list.json.blake2b", "wb") as f: f.write(hashlib.blake2b(b).digest()) -# Forge pure signature on hash +# Forge pure signature on hash, see https://github.com/jedisct1/minisign/issues/104 with open("server_list.json.minisig", "rb") as f: siglines = f.readlines() diff --git a/test_data/dummy/organization_list.json b/test_data/organization_list.json index 8c53044..8c53044 100644 --- a/test_data/dummy/organization_list.json +++ b/test_data/organization_list.json diff --git a/test_data/dummy/organization_list.json.minisig b/test_data/organization_list.json.minisig index 1fa546e..1fa546e 100644 --- a/test_data/dummy/organization_list.json.minisig +++ b/test_data/organization_list.json.minisig diff --git a/test_data/dummy/organization_list.json.tc_servlist.minisig b/test_data/organization_list.json.tc_servlist.minisig index a7fe41f..a7fe41f 100644 --- a/test_data/dummy/organization_list.json.tc_servlist.minisig +++ b/test_data/organization_list.json.tc_servlist.minisig diff --git a/test_data/dummy/other_list.json b/test_data/other_list.json index 25ba1a8..25ba1a8 100644 --- a/test_data/dummy/other_list.json +++ b/test_data/other_list.json diff --git a/test_data/dummy/other_list.json.minisig b/test_data/other_list.json.minisig index eaa2248..eaa2248 100644 --- a/test_data/dummy/other_list.json.minisig +++ b/test_data/other_list.json.minisig diff --git a/test_data/dummy/public.key b/test_data/public.key index 72676d3..72676d3 100644 --- a/test_data/dummy/public.key +++ b/test_data/public.key diff --git a/test_data/dummy/random.txt b/test_data/random.txt index b6fc4c6..b6fc4c6 100644 --- a/test_data/dummy/random.txt +++ b/test_data/random.txt diff --git a/test_data/real/organization_list-1.json b/test_data/real/organization_list-1.json deleted file mode 100644 index dd7776d..0000000 --- a/test_data/real/organization_list-1.json +++ /dev/null @@ -1 +0,0 @@ -{"v":1636532223,"organization_list":[{"display_name":{"da":"Dansk Sprogn\u00e6vn","en":"Danish Language Council"},"org_id":"http://idp.dsn.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Erhvervsakademi Aarhus","en":"Business Academy Aarhus"},"org_id":"http://adfs.eaaa.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"KMD DSPARE3","en":"KMD DSPARE3"},"org_id":"http://dans-support-04.dans-idp-dev01.northeurope.cloudapp.azure.com","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"KMD DSUP_PATCH1","en":"KMD DSUP_PATCH1"},"org_id":"https://dans-idp.kmd.dk:7080","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"KMD DANSWRC2","en":"KMD DANSWRC2"},"org_id":"http://dans-support-02.dans-dp-dev01.northeurope.cloudapp.azure.com","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"IBA Erhvervsakademi Kolding","en":"IBA International Business Academy"},"org_id":"http://sso.basyd.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Aarhus Maskinmesterskole","en":"Aarhus School of Marine and Technical Engineering"},"org_id":"https://wayf.aams.dk/simplesaml/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Maskinmesterskolen K\u00f8benhavn","en":"Copenhagen School of Marine Engineering and Technology Management"},"org_id":"http://auth.msk.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"DANS test1","en":"DANS test1"},"org_id":"https://dansidp-test1.stads.dk","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"KMD DPATCH","en":"KMD DPATCH"},"org_id":"http://dans-support-01.dans-idp-dev01.northeurope.cloudapp.azure.com","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"WAYF Orphanage [KUN for udviklere]","en":"WAYF Orphanage [for developers ONLY]"},"org_id":"https://orphanage.wayf.dk","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Danmarks Tekniske Universitet","en":"Technical University of Denmark (DTU)"},"org_id":"http://sts.ait.dtu.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"en":"Guests and others [guest.dtu.dk]","da":"G\u00e6ster og andre [guest.dtu.dk]"},"org_id":"https://guestauth.ait.dtu.dk/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"KMD DDEV2","en":"KMD DDEV2"},"org_id":"http://dans-support-03.dans-idp-dev01.northeurope.cloudapp.azure.com","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"International Business College","en":"International Business College"},"org_id":"http://fs.ibc.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"KP (tidligere PHM) [TEST]","en":"University College Copenhagen (formerly Metropolitan University College) [TEST]"},"org_id":"https://testlogin.phmetropol.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"KEA \u2013 K\u00f8benhavns Erhvervsakademi","en":"Copenhagen School of Design and Technology (KEA)"},"org_id":"http://adfs.kea.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"DANS UDV","en":"DANS UDV"},"org_id":"https://dansidp-udv.stads.dk","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Det Kgl. Bibliotek","en":"Royal Danish Library"},"org_id":"https://staff-idp-saml.kb.dk/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Designskolen Kolding","en":"Design School Kolding"},"org_id":"http://fs.dskd.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Fredericia Maskinmesterskole","en":"Fredericia Maskinmesterskole"},"org_id":"http://idp.fms.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"DANS test5","en":"DANS test5"},"org_id":"https://dansidp-test5.stads.dk","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Cphbusiness","en":"Cphbusiness"},"org_id":"http://adfs.cphbusiness.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Danmarks Medie- og Journalisth\u00f8jskole","en":"Danish School of Media and Journalism"},"org_id":"http://fs.dmjx.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"WAYF Orphanage [TEST]","en":"WAYF Orphanage [TEST]"},"org_id":"https://orphanage2.wayf.dk","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"College360","en":"College360"},"org_id":"http://adfs.college360.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Arkitektskolen Aarhus","en":"Aarhus School of Architecture"},"org_id":"http://sts.aarch.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Statens Museum for Kunst \u2013 SMK","en":"National Gallery of Denmark \u2013 SMK"},"org_id":"https://adfs.smk.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"KMD DINST","en":"KMD DINST"},"org_id":"http://dans-dev01-dans-idp-dev01.northeurope.cloudapp.azure.com","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Statsbiblioteket \u2013 ansatte","en":"State and University Library \u2013 employees"},"org_id":"http://sts.statsbiblioteket.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"K\u00f8benhavns Universitet","en":"University of Copenhagen"},"org_id":"http://federation.ku.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"zz wl2 (ny)","en":"zz wl2 (new)"},"org_id":"https://dans-idp.kmd.dk:7020","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Marstal Navigationsskole","en":"Marstal School of Navigation"},"org_id":"http://adfs.marnav.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"K\u00f8benhavns Professionsh\u00f8jskole","en":"University College Copenhagen"},"org_id":"https://login.kp.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Det Kongelige Danske Musikkonservatorium","en":"Royal Danish Academy of Music"},"org_id":"https://sts.windows.net/30be3e72-3ef8-4594-bfa3-6423b003e88c/","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Det Kongelige Danske Kunstakademis Billedkunstskoler","en":"Schools of Visual Arts, The Royal Danish Academy of Fine Arts"},"org_id":"https://sts.windows.net/7882421d-c23b-4c72-bf42-9280889dfb90/","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"KMD Test special IdP","en":"KMD Test special IdP"},"org_id":"https://dans-idp.kmd.dk:7005","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"DANS QA","en":"DANS QA"},"org_id":"https://dansidp-qa.stads.dk","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"UCL Erhvervsakademi og Professionsh\u00f8jskole","en":"UCL"},"org_id":"https://athome.ucl.dk/nidp/saml2/metadata","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"KMD DSUP_HFX","en":"KMD DSUP_HFX"},"org_id":"https://dans-idp.kmd.dk:7070","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"K\u00f8benhavns Universitet [TEST]","en":"University of Copenhagen [TEST]"},"org_id":"https://t-id.ku.dk/nidp/saml2/metadata","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"MARTEC","en":"MARTEC Maritime and Polytechnic University College"},"org_id":"http://fs.martec.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Rigsarkivet","en":"Danish National Archives"},"org_id":"http://idp.sa.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Fr\u00f3\u00f0skaparsetur F\u00f8roya","en":"University of the Faroe Islands","fo":"Fr\u00f3\u00f0skaparsetur F\u00f8roya"},"org_id":"http://adfs.setur.fo/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"en":"Open Test IdP []","da":"Open Test IdP []"},"org_id":"idp.entity.test","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"DANS TEST2","en":"DANS TEST2"},"org_id":"https://dansidp-test2.stads.dk","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"IT-Universitetet i K\u00f8benhavn","en":"IT University of Copenhagen"},"org_id":"https://wayf.itu.dk/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Aarhus Universitet [TEST]","en":"Aarhus University [TEST]"},"org_id":"https://wayft.au.dk","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"H\u00e1sk\u00f3li \u00cdslands","en":"University of Iceland","is":"H\u00e1sk\u00f3li \u00cdslands"},"org_id":"https://sts.windows.net/09fa5f0e-2118-4656-8529-677ed8fdbe78/","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"UC SYD","en":"University College South Denmark"},"org_id":"http://fg.ucsyd.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"en":"TeleDCIS [Guests]","da":"TeleDCIS [G\u00e6ster]"},"org_id":"https://member.teledcis.dk/guidp","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Region Hovedstaden","en":"Capital Region of Denmark"},"org_id":"http://fs.regionh.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"DANS Test3","en":"DANS Test3"},"org_id":"https://dansidp-test3.stads.dk","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"en":"Reykjav\u00edk University","da":"H\u00e1sk\u00f3linn \u00ed Reykjav\u00edk","is":"H\u00e1sk\u00f3linn \u00ed Reykjav\u00edk"},"org_id":"http://fs.ru.is/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"KMD DFAT","en":"KMD DFAT"},"org_id":"http://dans-support-05.dans-idp-dev01.northeurope.cloudapp.azure.com","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"KMD DWLS_UPGRADE","en":"KMD DWLS_UPGRADE"},"org_id":"http://dans-dev02-dans-idp-dev01.northeurope.cloudapp.azure.com","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Glasir","en":"Glasir T\u00f3rshavn College","fo":"Glasir"},"org_id":"http://adfs.glasir.fo/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Det Danske Sprog- og Litteraturselskab","en":"Society for Danish Language and Literature"},"org_id":"https://wayf.dsl.dk/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"TEC","en":"TEC"},"org_id":"http://adfs.tec.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Alexandra Instituttet","en":"Alexandra Institute"},"org_id":"https://sts.windows.net/4bda23cd-4a87-419b-a47d-7673130b2884/","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"SIMAC","en":"SIMAC"},"org_id":"http://fs.edu.simac.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"KMD DPERF1","en":"KMD DPERF1"},"org_id":"https://dans-idp.kmd.dk:7040","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Roskilde Universitet (RUC) [TEST]","en":"Roskilde University (RUC) [TEST]"},"org_id":"https://saml.signon-test.ruc.dk/idp","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"NemLog-In 3 [TEST]","en":"NemLog-In 3 [TEST]"},"org_id":"https://saml.test-devtest4-nemlog-in.dk","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"en":"DeiC \u2013 Danish e-Infrastructure Cooperation [PILOT]","da":"DeiC \u2013 Danish e-Infrastructure Cooperation [PILOT]"},"org_id":"https://idp.deic.dk","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"DANS test6","en":"DANS test6"},"org_id":"https://dansidp-test6.stads.dk","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Learnmark Horsens","en":"Learnmark Horsens"},"org_id":"http://adfs.learnmark.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Erhvervsakademi SydVest","en":"Business Academy SouthWest (EASV)"},"org_id":"http://sso.easv.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"NemID","en":"NemID"},"org_id":"https://nemlogin.wayf.dk","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Grenaa Gymnasium","en":"Grenaa Gymnasium"},"org_id":"http://fs4.grenaa-gym.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"DANS TEST4","en":"DANS TEST4"},"org_id":"https://dansidp-test4.stads.dk","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Professionsh\u00f8jskolen UCN","en":"UCN"},"org_id":"https://sts.windows.net/d6338997-214a-4f92-ba75-0397f10a84cc/","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Last Resort IdP [TEST]","en":"Last Resort IdP [TEST]"},"org_id":"https://dev.service.deic.dk","secure_internet_home":"https://eduvpn.deic.dk/","keyword_list":{"en":"prioritized"}},{"display_name":{"da":"KMD DSUP_PROD","en":"KMD DSUP_PROD"},"org_id":"https://dans-idp.kmd.dk:7090","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Syddansk Universitet","en":"University of Southern Denmark (SDU)"},"org_id":"https://sso.sdu.dk/wayf","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"K\u00f8benhavns Professionsh\u00f8jskole (tidligere Professionsh\u00f8jskolen Metropol)","en":"University College Copenhagen (formerly Metropolitan University College)"},"org_id":"https://login.phmetropol.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"DANS PRE","en":"DANS PRE"},"org_id":"https://dansidp-pre.stads.dk","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"SOSU \u00d8stjylland","en":"Basic Health Care College Eastern Jutland"},"org_id":"http://fs4.sosuoj.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"KMD DDEV3","en":"KMD DDEV3"},"org_id":"https://dans-idp.kmd.dk:7050","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"KMD DANSWRC4","en":"KMD DANSWRC4"},"org_id":"http://int-pr.dans-idp-dev01.northeurope.cloudapp.azure.com","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"KMD DANSWRC3","en":"KMD DANSWRC3"},"org_id":"http://int-qa.dans-idp-dev01.northeurope.cloudapp.azure.com","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Rungsted Gymnasium","en":"Rungsted Gymnasium"},"org_id":"http://login.rungsted-gym.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"DANS-QA3","en":"DANS-QA3"},"org_id":"https://dansidp-qa3.stads.dk","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"en":"DeiC Grand Unified IDP","da":"DeiC Grand Unified IDP"},"org_id":"https://guidp.deic.dk","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"[Oncology Venture A/S]","en":"[Oncology Venture A/S]"},"org_id":"https://sts.windows.net/df23cb97-8677-478f-88b5-d6c93d1a87fd/","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"ZBC \u2013 Zealand Business College","en":"ZBC \u2013 Zealand Business College"},"org_id":"http://adfs.zbc.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"VIA University College","en":"VIA University College"},"org_id":"http://fs.via.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Maskinmesterskolen K\u00f8benhavn [TEST]","en":"Copenhagen School of Marine Engineering and Technology Management [TEST]"},"org_id":"http://migration.wayf.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Pr\u00f3vstovan","en":"Pr\u00f3vstovan","fo":"Pr\u00f3vstovan"},"org_id":"https://sts.windows.net/b2d4664d-022f-47db-b771-62cc2e653147/","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Zealand \u2013 Sj\u00e6llands Erhvervsakademi","en":"Zealand"},"org_id":"http://fs.easj.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Hotel- og Restaurantskolen","en":"Copenhagen Hospitality College"},"org_id":"http://adfs.hrs.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Grand Unified IdP [TEST]","en":"Grand Unified IdP [TEST]"},"org_id":"https://test.guidp.deic.dk","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Frederikssund Gymnasium","en":"Frederikssund Gymnasium"},"org_id":"http://adfs.frsgym.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Det Jyske Musikkonservatorium","en":"Royal Academy of Music, Aarhus/Aalborg"},"org_id":"http://adfs.musikkons.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Rytmisk Musikkonservatorium (RMC)","en":"Rhythmic Music Conservatory"},"org_id":"https://sts.windows.net/d7aa303f-a31f-410a-b10f-26ee41af9e93/","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"KMD DANSWRC1","en":"KMD DANSWRC1"},"org_id":"http://int-test.dans-idp-dev01.northeurope.cloudapp.azure.com","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"en":"University College Copenhagen [ADFS:TEST]","da":"K\u00f8benhavns Professsionsh\u00f8jskole [ADFS:TEST]"},"org_id":"http://testlogin.kp.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"DeiC Last Resort IdP","en":"DeiC Last Resort IdP"},"org_id":"https://lridp.deic.dk","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Roskilde Universitet (RUC)","en":"Roskilde University (RUC)"},"org_id":"https://saml.signon.ruc.dk/idp","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Energimuseet","en":"Danish Museum of Energy"},"org_id":"https://sts.windows.net/46f7cafd-ebfa-40a6-98de-bb0ab0df227a/","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Erhvervsakademi MidtVest","en":"Erhvervsakademi MidtVest"},"org_id":"http://fs.eamv.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Copenhagen Business School","en":"Copenhagen Business School"},"org_id":"https://cas.cbs.dk/saml/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"NORDUnet A/S","en":"NORDUnet A/S"},"org_id":"https://idp.nordu.net/idp/shibboleth","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Uddannelsesministeriets It","en":"IT Department of the Ministry of Higher Education and Science"},"org_id":"https://idp.umit.dk","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"\u00d8SS-Samarbejdet","en":"OESS Cooperation"},"org_id":"https://wayfidp.oess.dk/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"KMD DPERF2","en":"KMD DPERF2"},"org_id":"https://dans-idp.kmd.dk:7060","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Rysensteen Gymnasium","en":"Rysensteen Gymnasium"},"org_id":"http://adfs.rysensteen.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Danmarks Meteorologiske Institut (DMI) [TEST]","en":"Danish Meteorological Institute (DMI) [TEST]"},"org_id":"http://fs.dmi.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Kr\u00e6ftens Bek\u00e6mpelse","en":"Danish Cancer Society"},"org_id":"https://sts.windows.net/9ffd9551-461b-4f09-8b17-b822440a6649/","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Region Midtjylland","en":"Central Denmark Region"},"org_id":"https://samlapp.rm.dk/nidp/saml2/metadata","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"DANS TEST","en":"DANS TEST"},"org_id":"https://dansidp-test.stads.dk","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"MR-Forskningssektionen (DRCMR)","en":"Danish Research Centre for Magnetic Resonance"},"org_id":"https://wayf.drcmr.dk/auth","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"NemLog-in [TEST]","en":"NemLog-in [TEST]"},"org_id":"https://saml.test-nemlog-in.dk/","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Vordingborg Gymnasium & HF","en":"Vordingborg Gymnasium & HF"},"org_id":"http://adfs.vordingborg-gym.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Erhvervsakademi Dania","en":"Dania Academy"},"org_id":"https://wayfeadania.itcn.dk/simplesaml/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Professionsh\u00f8jskolen Absalon","en":"Absalon University College"},"org_id":"https://sts.pha.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Aalborg Universitet","en":"Aalborg University"},"org_id":"https://wayf.aau.dk","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Aarhus Universitet","en":"Aarhus University"},"org_id":"https://wayf.au.dk","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Region Sj\u00e6lland","en":"Region Zealand"},"org_id":"http://wayf.regionsjaelland.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Paderup Gymnasium","en":"Paderup Gymnasium"},"org_id":"http://fs4.paderup-gym.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"KMD DSPARE2","en":"KMD DSPARE2"},"org_id":"https://dans-idp.kmd.dk:7030","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Forsvarets Bibliotekscenter","en":"Danish Defence Library Center "},"org_id":"https://auth.fak.dk/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"KMD DSPARE1","en":"KMD DSPARE1"},"org_id":"https://dans-idp.kmd.dk:7010","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Region Midtjylland [TEST]","en":"Central Denmark Region [TEST]"},"org_id":"https://samltest.rm.dk/nidp/saml2/metadata","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"eIDAS [integrationstest]","en":"eIDAS [integration test]"},"org_id":"https://eidasconnector.test.eid.digst.dk/idp","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Det Kongelige Akademi \u2013 Arkitektur, Design, Konservering","en":"Royal Danish Academy \u2013 Architecture, Design, Conservation"},"org_id":"http://sts.kadk.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"Ans\u00f8gningsportalen (tidligere STADS-DANS)","en":"Application Portal (formerly STADS-DANS)"},"org_id":"https://dansidp.stads.dk","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"da":"K\u00f8benhavns Professionsh\u00f8jskole [tidligere Professionsh\u00f8jskolen UCC]","en":"University College Copenhagen [formerly University College Capital]"},"org_id":"http://adfs.ucc.dk/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"gl":"Ilisimatusarfik","da":"Ilisimatusarfik","en":"University of Greenland"},"org_id":"http://adfs.uni.gl/adfs/services/trust","secure_internet_home":"https://eduvpn.deic.dk/"},{"display_name":{"ru":"\u0422\u0430\u0440\u0442\u0443\u0441\u043a\u0438\u0439 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0438\u0442\u0435\u0442","fi":"Tarton yliopisto","et":"Tartu \u00dclikool","en":"University of Tartu"},"org_id":"https://auth.ut.ee/idp/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.eenet.ee/"},{"display_name":{"et":"KBFI","en":"KBFI"},"org_id":"https://memm.hep.kbfi.ee/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.eenet.ee/"},{"display_name":{"et":"TalTech","en":"TalTech"},"org_id":"https://idp.ttu.ee/simplesaml/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.eenet.ee/"},{"display_name":{"et":"Eesti Maa\u00fclikool","en":"Estonian University of Life Sciences"},"org_id":"https://auth.emu.ee/emu-auth/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.eenet.ee/"},{"display_name":{"et":"Tallinna \u00dclikool","en":"Tallinn University"},"org_id":"https://passwd.tlu.ee/taatauth/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.eenet.ee/"},{"display_name":{"et":"Tallinna Tervishoiu K\u00f5rgkool","en":"Tallinn Health Care College"},"org_id":"https://taat.ttk.ee/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.eenet.ee/"},{"display_name":{"et":"TT\u00dc K\u00dcBERNEETIKA INSTITUUT","en":"INSTITUTE of CYBERNETICS at TUT"},"org_id":"https://taat.ioc.ee/simplesamlphp/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.eenet.ee/"},{"display_name":{"et":"Eesti Infotehnoloogia Kolled\u017e","en":"The Estonian Information Technology College"},"org_id":"https://itcollege.ois.ee/simplesamlphp/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.eenet.ee/"},{"display_name":{"et":"Eesti Kunstiakadeemia","en":"Estonian Academy of Arts"},"org_id":"https://artun.ois.ee/simplesamlphp/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.eenet.ee/"},{"display_name":{"et":"Sisekaitseakadeemia","en":"Estonian Academy of Security Sciences"},"org_id":"https://sisekaitse.ois.ee/simplesamlphp/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.eenet.ee/"},{"display_name":{"et":"Tartu Tervishoiu K\u00f5rgkool","en":"Tartu Healthcare College"},"org_id":"https://siseveeb.nooruse.ee/sso/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.eenet.ee/"},{"display_name":{"et":"Tartu T\u00e4iskasvanute G\u00fcmnaasium","en":"Tartu Upper Secondary School for Adults"},"org_id":"https://videvik.ag.tartu.ee/xconn_taat/www/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.eenet.ee/"},{"display_name":{"et":"Eesti Muusika- ja Teatriakadeemia","en":"Estonian Academy of Music and Theatre"},"org_id":"https://taat.eamt.ee/taat/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.eenet.ee/"},{"display_name":{"et":"Eesti keele instituut","en":"Institute of the Estonian Language"},"org_id":"https://www.eki.ee/simplesamlphp/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.eenet.ee/"},{"display_name":{"et":"EENet","en":"EENet"},"org_id":"https://eenet.harid.ee/sso/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.eenet.ee/"},{"display_name":{"et":"Tallinna Majanduskool","en":"Tallinn School of Economics"},"org_id":"https://taat.tmk.edu.ee/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.eenet.ee/"},{"display_name":{"et":"V\u00f5ru G\u00fcmnaasium","en":"Voru Gymnaasium"},"org_id":"https://voru.harid.ee/sso/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.eenet.ee/"},{"display_name":{"et":"P\u00e4rnu Koidula G\u00fcmnaasium","en":"Parnu Koidula Gymnasium"},"org_id":"https://idp.koidulag.edu.ee/taat/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.eenet.ee/"},{"display_name":{"et":"Tartu Kutsehariduskeskus","en":"Tartu Vocational Education Centre"},"org_id":"https://taat.khk.ee:5080/simplesaml/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.eenet.ee/"},{"display_name":{"et":"Tallinna 32. Keskkool","en":"Tallinn Secondary School No 32"},"org_id":"https://taat.32kk.edu.ee:7443/simplesaml/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.eenet.ee/"},{"display_name":{"et":"Tallinna Tehnikak\u00f5rgkool AD","en":"TTK University of Applied Sciences"},"org_id":"https://taat2.tktk.ee/simplesamlphp/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.eenet.ee/"},{"display_name":{"et":"Estonian Business School","en":"Estonian Business School"},"org_id":"http://adfs.ebs.ee/adfs/services/trust","secure_internet_home":"https://eduvpn.eenet.ee/"},{"display_name":{"et":"Eesti Lennuakadeemia","en":"Estonian Aviation Academy"},"org_id":"https://ssp.eava.ee/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.eenet.ee/"},{"display_name":{"et":"Eesti Ettev\u00f5tlusk\u00f5rgkool Mainor","en":"Estonian Entrepreneurship University Of Applied Sciences"},"org_id":"https://simplesaml.eek.ee/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.eenet.ee/"},{"display_name":{"en":"Certia Oy","sv":"Certia Oy","fi":"Certia Oy"},"org_id":"https://salpa.certia.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"Centria University of Applied Sciences","sv":"Centria yrkesh\u00f6gskola","fi":"Centria ammattikorkeakoulu"},"org_id":"https://idp.cou.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"National Audiovisual institute","sv":"Nationella audiovisuella institutet","fi":"Kansallinen audiovisuaalinen instituutti"},"org_id":"http://fs.kavi.fi/adfs/services/trust","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"Metropolia University of Applied Sciences","sv":"Metropolia yrkesh\u00f6gskola","fi":"Metropolia Ammattikorkeakoulu"},"org_id":"https://idp.metropolia.fi/idp","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"Oulu University of Applied Sciences","sv":"Yrkesh\u00f6gskolan i Ule\u00e5borg","fi":"Oulun ammattikorkeakoulu"},"org_id":"https://idp.oamk.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"University of Oulu","sv":"Ule\u00e5borgs universitet","fi":"Oulun yliopisto"},"org_id":"https://login.oulu.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"University of Lapland","sv":"Lapplands universitet","fi":"Lapin yliopisto"},"org_id":"https://idp.ulapland.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"Finnish Institute for Health and Welfare","sv":"Institutet f\u00f6r h\u00e4lsa och v\u00e4lf\u00e4rd","fi":"Terveyden ja hyvinvoinnin laitos"},"org_id":"https://tunnistus.thl.fi/idp","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"Satakunta University of Applied Sciences","sv":"Satakunnan ammattikorkeakoulu","fi":"Satakunnan ammattikorkeakoulu"},"org_id":"https://idp.samk.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/","keyword_list":{"fi":"samk","sv":"samk","en":"samk"}},{"display_name":{"en":"Aalto University","sv":"Aalto-universitetet","fi":"Aalto-yliopisto"},"org_id":"https://idp.aalto.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"University of Eastern Finland","sv":"\u00d6stra Finlands universitet","fi":"It\u00e4-Suomen yliopisto"},"org_id":"https://idp.uef.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"Diaconia University of Applied Sciences","sv":"Diakonia-ammattikorkeakoulu","fi":"Diakonia-ammattikorkeakoulu"},"org_id":"https://idp.diak.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"Hanken School of Economics","sv":"Hanken Svenska handelsh\u00f6gskolan","fi":"Hanken Svenska handelsh\u00f6gskolan"},"org_id":"https://idp.shh.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"HAAGA-HELIA University of Applied Sciences","sv":"HAAGA-HELIA yrkesh\u00f6gskola","fi":"HAAGA-HELIA ammattikorkeakoulu"},"org_id":"https://idp.haaga-helia.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/","keyword_list":{"en":"Haaga-Helia, University of Applied Sciences, Helsinki, Porvoo, Vierum\u00e4ki","sv":"Haaga-Helia, Yrkesh\u00f6gskolan, Helsinki, Porvoo, Vierum\u00e4ki","fi":"Haaga-Helia, ammattikorkeakoulu, Helsinki, Porvoo, Vierum\u00e4ki"}},{"display_name":{"en":"Jyv\u00e4skyl\u00e4 University of Applied Sciences","sv":"JAMK","fi":"Jyv\u00e4skyl\u00e4n ammattikorkeakoulu"},"org_id":"https://idp2.jamk.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"Turku University of Applied Sciences","sv":"\u00c5bo yrkesh\u00f6gskola","fi":"Turun ammattikorkeakoulu"},"org_id":"https://idp1.turkuamk.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"National Archives Service","sv":"Riksarkivet","fi":"Kansallisarkisto"},"org_id":"http://fs.narc.fi/adfs/services/trust","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"Kajaani University of Applied Sciences","sv":"Kajaanin ammattikorkeakoulu Oy","fi":"Kajaanin ammattikorkeakoulu Oy"},"org_id":"https://kamidp01.kamit.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"Government ICT Centre Valtori","sv":"Statens center f\u00f6r informations- och kommunikationsteknik","fi":"Valtion tieto- ja viestint\u00e4tekniikkakeskus Valtori"},"org_id":"http://fs.valtori.fi/adfs/services/trust","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"Tampere Universities","sv":"Tampere Universities","fi":"Tampereen korkeakoulut"},"org_id":"https://idp.tuni.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/","keyword_list":{"en":"Tampere tuni.fi TUNI Tampere3","fi":"Tampere tuni.fi TUNI Tampere3"}},{"display_name":{"en":"University of Turku","sv":"\u00c5bo universitet","fi":"Turun yliopisto"},"org_id":"https://sso.utu.fi/sso-idp","secure_internet_home":"https://eduvpn1.funet.fi/","keyword_list":{"en":"utu","sv":"utu","fi":"utu"}},{"display_name":{"en":"Kuopio University Hospital","sv":"Kuopio universitetssjukhus","fi":"Kuopion yliopistollinen sairaala"},"org_id":"https://sts.psshp.fi/idp/haka","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"CSC - IT Center for Science Ltd.","sv":"CSC - Tieteen tietotekniikan keskus Oy","fi":"CSC - Tieteen tietotekniikan keskus Oy"},"org_id":"https://idp.csc.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"LUT University","sv":"LUT-universitetet","fi":"LUT-yliopisto"},"org_id":"https://idp.lut.fi","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"Arcada","sv":"Arcada","fi":"Arcada"},"org_id":"https://tullbommen.arcada.fi/simplesaml/","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"\u00c5bo Akademi University","sv":"\u00c5bo Akademi","fi":"\u00c5bo Akademi"},"org_id":"https://idp.abo.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/","keyword_list":{"en":"\u00c5A","sv":"\u00c5A"}},{"display_name":{"en":"The Emergency Services College","sv":"R\u00e4ddningsinstitutet","fi":"Pelastusopisto"},"org_id":"https://tunnistus.pelastusopisto.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"University of Helsinki","sv":"Helsingfors universitet","fi":"Helsingin yliopisto"},"org_id":"https://login.helsinki.fi/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"Lapland University of Applied Sciences","sv":"Lapplands Yrkesh\u00f6gskola","fi":"Lapin ammattikorkeakoulu"},"org_id":"https://idp.lapinamk.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"Finnish Meteorological Institute","sv":"Meteorologiska institutet","fi":"Ilmatieteen laitos"},"org_id":"https://sipuli.fmi.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"Funidata IDP","sv":"Funidata IDP","fi":"Funidata IDP"},"org_id":"https://idp.funidata.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"South-Eastern Finland University of Applied Sciences","sv":"Kaakkois-Suomen ammattikorkeakoulu","fi":"Kaakkois-Suomen ammattikorkeakoulu"},"org_id":"https://xidp.xamk.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/","keyword_list":{"en":"xamk xamk.fi south-eastern finland","fi":"xamk xamk.fi kaakkois-suomi","sv":"xamk xamk.fi"}},{"display_name":{"en":"HUMAK University of Applied Sciences","sv":"Humanistiska Yrkesh\u00f6gskola","fi":"Humanistinen ammattikorkeakoulu"},"org_id":"https://rap.humak.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"Finnish Environment Institute","sv":"Finlands milj\u00f6central","fi":"Suomen ymp\u00e4rist\u00f6keskus"},"org_id":"http://fs.ymparisto.fi/adfs/services/trust","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"University of Jyv\u00e4skyl\u00e4","sv":"Jyv\u00e4skyl\u00e4 universitet","fi":"Jyv\u00e4skyl\u00e4n yliopisto"},"org_id":"https://login.jyu.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"National Defence University","sv":"F\u00f6rvarsh\u00f6gskolan","fi":"Maanpuolustuskorkeakoulu"},"org_id":"https://tunnistus.mpkkfu.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"Laurea University of Applied Sciences","sv":"Laurea yrkeh\u00f6gskola","fi":"Laurea-ammattikorkeakoulu"},"org_id":"http://tunnistus.laurea.fi/adfs/services/trust","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"University of the Arts Helsinki","sv":"Konstuniversitetet","fi":"Taideyliopisto"},"org_id":"https://idp.uniarts.fi/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"Police University College","sv":"Polisyrkesh\u00f6gskolan","fi":"Poliisiammattikorkeakoulu"},"org_id":"https://tunnistus.smedu.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"Savonia University of Applied Sciences","sv":"Savonia Yrkesh\u00f6gskola","fi":"Savonia-ammattikorkeakoulu"},"org_id":"https://idp.savonia.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"Vaasa University of Applied Sciences","sv":"Vasa yrkesh\u00f6gskola","fi":"Vaasan ammattikorkeakoulu"},"org_id":"https://idp.vamk.fi/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"University of Vaasa","sv":"Vasa Universitet","fi":"Vaasan yliopisto"},"org_id":"https://login.uwasa.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"LAB University of Applied Sciences","sv":"Yrkesh\u00f6gskolan Lab","fi":"LAB-ammattikorkeakoulu"},"org_id":"https://idp.lab.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"Federation of Finnish Learned Societies","sv":"Vetenskapliga samfundens delegation","fi":"Tieteellisten seurain valtuuskunta"},"org_id":"https://idp.tsv.fi/saml2/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"Sein\u00e4joki University of Applied Sciences","sv":"Sein\u00e4joki yrkesh\u00f6gskola","fi":"Sein\u00e4joen ammattikorkeakoulu"},"org_id":"https://idp.seamk.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"\u00c5land University of Applied Sciences","sv":"H\u00f6gskolan p\u00e5 \u00c5land","fi":"H\u00f6gskolan p\u00e5 \u00c5land"},"org_id":"https://idp.ha.ax/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"Novia University of Applied Sciences","sv":"Yrkesh\u00f6gskolan Novia","fi":"Yrkesh\u00f6gskolan Novia"},"org_id":"https://idp1.novia.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"H\u00e4me University of Applied Sciences","sv":"HAMK Yrkesh\u00f6gskola","fi":"H\u00e4meen ammattikorkeakoulu"},"org_id":"https://shibbo.hamk.fi/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"Karelia University of Applied Sciences","sv":"Karelia yrkeh\u00f6gskola","fi":"Karelia-ammattikorkeakoulu"},"org_id":"https://idp.pkamk.fi/idp/shibboleth","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"Finnish Institute for Health and Welfare (THL)-NEW","sv":"Institutet f\u00f6r h\u00e4lsa och v\u00e4lf\u00e4rd (THL)-NY","fi":"Terveyden ja hyvinvoinnin laitos (THL)-UUSI"},"org_id":"http://tunnistaminen.thl.fi/adfs/services/trust","secure_internet_home":"https://eduvpn1.funet.fi/"},{"display_name":{"en":"GIP RENATER","fr":"GIP RENATER"},"org_id":"https://idp.renater.fr/idp/shibboleth","secure_internet_home":"https://eduvpn-poc.renater.fr/"},{"display_name":{"de":"DFN-AAI Integration + Test IdP","en":"DFN-AAI Integration + Test IdP"},"org_id":"https://aai-integration.dfn.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Max-Delbr\u00fcck-Centrum f\u00fcr molekulare Medizin","en":"Max Delbr\u00fcck Center for Molecular Medicine"},"org_id":"https://aai-mdc1.mdc-berlin.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Speyer","en":"Universit\u00e4t Speyer"},"org_id":"https://aai.dhv-speyer.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Helmholtz Zentrum M\u00fcnchen GmbH (HMGU)","en":"Helmholtz Zentrum Muenchen GmbH (HMGU)"},"org_id":"https://aai.helmholtz-muenchen.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"IPK Gatersleben","en":"IPK Gatersleben"},"org_id":"https://aai.ipk-gatersleben.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Potsdam-Institut f\u00fcr Klimafolgenforschung","en":"Potsdam Institute for Climate Impact Research"},"org_id":"https://aai.pik-potsdam.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Ruhr-Universit\u00e4t Bochum","en":"Ruhr-Universit\u00e4t Bochum"},"org_id":"https://aai.ruhr-uni-bochum.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Leipzig","en":"Leipzig University"},"org_id":"https://aai.rz.uni-leipzig.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Technische Hochschule Wildau","en":"Technical University of Applied Sciences Wildau"},"org_id":"https://aai.th-wildau.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Fachhochschule Potsdam","en":"Fachhochschule Potsdam, University of Applied Scienes"},"org_id":"https://account.fh-potsdam.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"FID-Recht (VHO)","en":"FID-Recht (VHO)"},"org_id":"https://auth.vifa-recht.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Musik Freiburg","en":"University of Music Freiburg"},"org_id":"https://authent.mh-freiburg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Badische Landesbibliothek","en":"Badische Landesbibliothek"},"org_id":"https://blblogin.blb-karlsruhe.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"THGA Bochum","en":"THGA Bochum"},"org_id":"https://checkin.thga.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"TU Bergakademie Freiberg","en":"TU Bergakademie Freiberg"},"org_id":"https://crux.hrz.tu-freiberg.de/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Charit\u00e9 - Universit\u00e4tsmedizin Berlin","en":"Charite - Universitaetsmedizin Berlin"},"org_id":"https://dfnaai.charite.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Deutsches Krebsforschungszentrum (DKFZ)","en":"Deutsches Krebsforschungszentrum (DKFZ)"},"org_id":"https://dkfzshib.inet.dkfz-heidelberg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Technische Universit\u00e4t Berlin","en":"Technische Universit\u00e4t Berlin"},"org_id":"https://ephraim.tu-berlin.de/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"DFN Login Extern","en":"DFN Login Extern"},"org_id":"https://extlogin.dfn.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Ferdinand-Braun-Institut, Leibniz-Institut f\u00fcr H\u00f6chstfrequenztechnik","en":"Ferdinand-Braun-Institute, Leibniz-Institut fuer Hoechstfrequenztechnik"},"org_id":"https://fbh-idp.fbh-berlin.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hertie School","en":"Hertie School"},"org_id":"https://hertie.sso.academiccloud.de/simplesaml/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Forschungsinstitut f\u00fcr Nutztierbiologie (FBN)","en":"Research Institute for farm animal biology (FBN)"},"org_id":"https://hotaai.fbn-dummerstorf.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Freie Universit\u00e4t Berlin","en":"Freie Universit\u00e4t Berlin"},"org_id":"https://identity.fu-berlin.de/idp-fub","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Wirtschaft und Recht Berlin","en":"Berlin School of Economics and Law (HWR)"},"org_id":"https://identity.hwr-berlin.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Medizinische Hochschule Brandenburg","en":"Brandenburg Medical School"},"org_id":"https://idp-dev.mhb-fontane.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Nachhaltige Entwicklung Eberswalde","en":"Eberswalde University for Sustainable Development"},"org_id":"https://idp-prod.hnee.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Otto-von-Guericke-Universit\u00e4t Magdeburg (OVGU)","en":"Otto-von-Guericke-University Magdeburg (OVGU)"},"org_id":"https://idp-serv.uni-magdeburg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Musik Dresden","en":"Hochschule fuer Musik Dresden"},"org_id":"https://idp-vw.hfmdd.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hfoed - FB AIV","en":"Hfoed - FB AIV"},"org_id":"https://idp.aiv.hfoed.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"BA Riesa","en":"BA Riesa"},"org_id":"https://idp.ba-riesa.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Berufsakademie Sachsen","en":"Berufsakademie Sachsen"},"org_id":"https://idp.ba-sachsen.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"bib International College","en":"bib International College"},"org_id":"https://idp.bib.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"MPI fuer Biochemie","en":"MPI of Biochemistry"},"org_id":"https://idp.biochem.mpg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"MPI f\u00fcr Biophysik","en":"MPI of Biophysics"},"org_id":"https://idp.biophys.mpg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"BSB M\u00fcnchen","en":"BSB M\u00fcnchen"},"org_id":"https://idp.bsb-muenchen.de/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Bibliotheksservice-Zentrum Baden-W\u00fcrttemberg","en":"Bibliotheksservice-Zentrum Baden-Wuerttemberg"},"org_id":"https://idp.bsz-bw.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Burg Giebichenstein Kunsthochschule Halle","en":"Burg Giebichenstein University of Art and Design Halle"},"org_id":"https://idp.burg-halle.eu/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"DHBW CAS","en":"DHBW CAS"},"org_id":"https://idp.cas.dhbw.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Frankfurt University of Applied Sciences","en":"Frankfurt University of Applied Sciences"},"org_id":"https://idp.cit.frankfurt-university.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"DARIAH","en":"DARIAH"},"org_id":"https://idp.de.dariah.eu/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Deutsches Elektronen-Synchrotron DESY","en":"Deutsches Elektronen-Synchrotron DESY"},"org_id":"https://idp.desy.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"DFN-CERT Services GmbH","en":"DFN-CERT Services GmbH"},"org_id":"https://idp.dfn-cert.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"DFN-Verein Gesch\u00e4ftsstelle","en":"DFN Office"},"org_id":"https://idp.dfn.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"DHBW L\u00f6rrach","en":"DHBW L\u00f6rrach"},"org_id":"https://idp.dhbw-loerrach.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"DHBW Mannheim","en":"DHBW Mannheim"},"org_id":"https://idp.dhbw-mannheim.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"DHBW Villingen-Schwenningen","en":"DHBW Villingen-Schwenningen"},"org_id":"https://idp.dhbw-vs.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"DHBW","en":"DHBW"},"org_id":"https://idp.dhbw.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Deutsche Hochschule der Polizei","en":"German Police University"},"org_id":"https://idp.dhpol.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Deutsches Klimarechenzentrum GmbH (DKRZ)","en":"Deutsches Klimarechenzentrum GmbH (DKRZ)"},"org_id":"https://idp.dkrz.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"DLR - Deutsches Zentrum fuer Luft- und Raumfahrt e.V.","en":"DLR - Deutsches Zentrum fuer Luft- und Raumfahrt e.V."},"org_id":"https://idp.dlr.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Deutsches Schifffahrtsmuseum (DSM)","en":"Deutsches Schifffahrtsmuseum (DSM)"},"org_id":"https://idp.dsm.museum/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Ernst-Abbe-Hochschule Jena","en":"Ernst-Abbe-Hochschule Jena"},"org_id":"https://idp.eah-jena.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Evangelische Hochschule Dresden","en":"Evangelische Hochschule Dresden"},"org_id":"https://IDP.ehs-dresden.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"ESMT Berlin","en":"ESMT Berlin"},"org_id":"https://idp.esmt.org/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"ESO - European Southern Observatory","en":"ESO - European Southern Observatory"},"org_id":"https://idp.eso.org/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Europa-Universit\u00e4t Viadrina","en":"Europa-Universit\u00e4t Viadrina"},"org_id":"https://idp.europa-uni.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Evangelische Hochschule RWL","en":"Protestant University of Applied Sciences RWL"},"org_id":"https://idp.evh-bochum.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Evangelische Hochschule N\u00fcrnberg","en":"Evangelische Hochschule Nuernberg"},"org_id":"https://idp.evhn.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Fachhochschule Dortmund","en":"Dortmund University of Applied Sciences and Arts"},"org_id":"https://idp.fh-dortmund.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule D\u00fcsseldorf (Generation 1)","en":"Hochschule D\u00fcsseldorf (Gen 1)"},"org_id":"https://idp.fh-duesseldorf.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"FH Erfurt","en":"FH Erfurt"},"org_id":"https://idp.fh-erfurt.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Fachhochschule Kiel","en":"Kiel University of Applied Sciences"},"org_id":"https://idp.fh-kiel.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"FH M\u00fcnster","en":"FH Muenster"},"org_id":"https://idp.fh-muenster.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Offenburg","en":"Offenburg University of Applied Sciences"},"org_id":"https://idp.fh-offenburg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Technische Hochschule Rosenheim","en":"Technical University of Applied Sciences Rosenheim"},"org_id":"https://idp.fh-rosenheim.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Fachhochschule S\u00fcdwestfalen","en":"South Westphalia University of Applied Sciences"},"org_id":"https://idp.fh-swf.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Trier","en":"Trier University of Applied Sciences"},"org_id":"https://idp.fh-trier.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Fachhochschule Westk\u00fcste","en":"Fachhochschule Westk\u00fcste"},"org_id":"https://idp.fh-westkueste.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Fritz-Haber-Institut","en":"Fritz-Haber-Institut"},"org_id":"https://idp.fhi-berlin.mpg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule W\u00fcrzburg-Schweinfurt","en":"Hochschule W\u00fcrzburg-Schweinfurt"},"org_id":"https://idp.fhws.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Filmakademie Baden-Wuerttemberg (Prod)","en":"Filmakademie Baden-Wuerttemberg (Prod)"},"org_id":"https://idp.filmakademie.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"FIZ Karlsruhe","en":"FIZ Karlsruhe"},"org_id":"https://idp.fiz-karlsruhe.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Fraunhofer-Gesellschaft","en":"Fraunhofer-Gesellschaft"},"org_id":"https://idp.fraunhofer.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"FZI Forschungszentrum Informatik","en":"FZI Forschungszentrum Informatik"},"org_id":"https://idp.fzi.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"GEOMAR Helmholtz-Zentrum f\u00fcr Ozeanforschung Kiel","en":"GEOMAR Helmholtz Centre for Ocean Research Kiel"},"org_id":"https://idp.geomar.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"GESIS - Leibniz-Institut f\u00fcr Sozialwissenschaften","en":"GESIS \u2013 Leibniz-Institute for the Social Sciences"},"org_id":"https://idp.gesis.org/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Helmholtz-Zentrum Potsdam Deutsches GeoForschungsZentrum GFZ","en":"Helmholtz Centre Potsdam GFZ German Research Centre for Geosciences"},"org_id":"https://idp.gfz-potsdam.de/cas/idp","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"GSI Helmholtzzentrum f\u00fcr Schwerionenforschung GmbH","en":"GSI Helmholtzzentrum f\u00fcr Schwerionenforschung GmbH"},"org_id":"https://idp.gsi.de","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Bonn-Rhein-Sieg IDM","en":"Bonn-Rhein-Sieg University of Applied Sciences IDM"},"org_id":"https://idp.h-brs.de/nidp/saml2/metadata","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Herzog August Bibliothek Wolfenbuettel","en":"Herzog August Bibliothek Wolfenbuettel"},"org_id":"https://idp.hab.de/simplesaml","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Landshut","en":"University of Applied Sciences Landshut"},"org_id":"https://idp.haw-landshut.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"HAWK Hochschule Hildesheim/Holzminden/G\u00f6ttingen","en":"HAWK University Hildesheim/Holzminden/G\u00f6ttingen"},"org_id":"https://idp.hawk.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"HafenCity Universit\u00e4t Hamburg","en":"HafenCity Universit\u00e4t Hamburg"},"org_id":"https://idp.hcu-hamburg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule der Medien Stuttgart","en":"Hochschule der Medien Stuttgart"},"org_id":"https://idp.hdm-stuttgart.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Frankfurt","en":"Universit\u00e4t Frankfurt"},"org_id":"https://idp.hebis.de/uni-frankfurt","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"DHBW Heilbronn","en":"DHBW Heilbronn"},"org_id":"https://idp.heilbronn.dhbw.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Helmholtz-Zentrum Berlin f\u00fcr Materialien und Energie GmbH (HZB)","en":"Helmholtz-Zentrum Berlin f\u00fcr Materialien und Energie GmbH (HZB)"},"org_id":"https://idp.helmholtz-berlin.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Helmholtz-Zentrum f\u00fcr Infektionsforschung GmbH [HZI]","en":"Helmholtz Center for Infection Research GmbH [HZI]"},"org_id":"https://idp.helmholtz-hzi.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Helmholtz-Gemeinschaft Deutscher Forschungszentren e.V.","en":"Helmholtz Association of German Research Centres e.V."},"org_id":"https://idp.helmholtz.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Helmholtz-Zentrum hereon GmbH","en":"Helmholtz-Zentrum hereon GmbH"},"org_id":"https://idp.hereon.de/auth/realms/hereon","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Bildende K\u00fcnste Dresden","en":"Academy of fine arts Dresden"},"org_id":"https://idp.hfbk-dresden.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"HfG Hochschule f\u00fcr Gestaltung","en":"HfG Hochschule f\u00fcr Gestaltung"},"org_id":"https://idp.hfg-gmuend.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"IDP - Hochschule f\u00fcr Gestaltung Offenbach am Main","en":"IDP - University of Art and Design - Offenbach am Main"},"org_id":"https://idp.hfg-offenbach.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Musik und Darstellende Kunst (HfMDK) Frankfurt am Main","en":"University of Music and Performing Arts (HfMDK) Frankfurt/Main"},"org_id":"https://idp.hfmdk-frankfurt.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Musik des Saarlandes","en":"Hochschule f\u00fcr Musik des Saarlandes"},"org_id":"https://idp.hfmsaar.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Musik und Tanz K\u00f6ln","en":"Hochschule f\u00fcr Musik und Tanz K\u00f6ln"},"org_id":"https://idp.hfmt-koeln.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Grafik und Buchkunst Leipzig","en":"Academy of Fine Arts Leipzig"},"org_id":"https://idp.hgb-leipzig.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Musik und Theater Leipzig","en":"University for music and theatre Leipzig"},"org_id":"https://idp.hmt-leipzig.de/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Musik und Theater Rostock","en":"Rostock University of Music and Drama"},"org_id":"https://idp.hmt-rostock.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Musik, Theater und Medien Hannover","en":"Hanover University of Music, Drama and Media"},"org_id":"https://idp.hmtm-hannover.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Biberach","en":"Hochschule Biberach"},"org_id":"https://idp.hochschule-bc.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Angewandte Wissenschaften Hof","en":"University of Applied Sciences Hof"},"org_id":"https://idp.hof-university.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Technische Universit\u00e4t Darmstadt","en":"Technical University of Darmstadt"},"org_id":"https://idp.hrz.tu-darmstadt.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Justus-Liebig-Universit\u00e4t Gie\u00dfen","en":"Justus Liebig University Giessen"},"org_id":"https://idp.hrz.uni-giessen.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Kassel","en":"Universit\u00e4t Kassel"},"org_id":"https://idp.hrz.uni-kassel.de/idp/shibboleth-idp","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Anhalt","en":"Anhalt University of Applied Sciences"},"org_id":"https://idp.hs-anhalt.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Ansbach IDP","en":"Hochschule Ansbach IDP"},"org_id":"https://idp.hs-ansbach.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Bochum","en":"Bochum University Of Applied Sciences"},"org_id":"https://idp.hs-bochum.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Bremen","en":"City University of applied sciences Bremen"},"org_id":"https://idp.hs-bremen.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Bremerhaven","en":"Hochschule Bremerhaven University of Applied Sciences"},"org_id":"https://idp.hs-bremerhaven.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Coburg","en":"Hochschule Coburg"},"org_id":"https://idp.hs-coburg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Emden/Leer","en":"University of Applied Sciences Emden/Leer"},"org_id":"https://idp.hs-emden-leer.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Esslingen","en":"Esslingen University of Applied Sciences"},"org_id":"https://idp.hs-esslingen.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Flensburg","en":"Flensburg University of Applied Sciences"},"org_id":"https://idp.hs-flensburg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Gesundheit","en":"Hochschule f\u00fcr Gesundheit"},"org_id":"https://idp.hs-gesundheit.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Hannover","en":"Hochschule Hannover"},"org_id":"https://idp.hs-hannover.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"HS-Harz","en":"HS-Harz"},"org_id":"https://idp.hs-harz.de/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Heilbronn","en":"Heilbronn University"},"org_id":"https://idp.hs-heilbronn.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Karlsruhe","en":"University of Applied Sciences Karlsruhe"},"org_id":"https://idp.hs-karlsruhe.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr \u00f6ffentliche Verwaltung Kehl","en":"University of Applied Sciences Kehl"},"org_id":"https://idp.hs-kehl.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Kempten","en":"Kempten University of Applied Sciences"},"org_id":"https://idp.hs-kempten.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Koblenz","en":"Hochschule Koblenz"},"org_id":"https://idp.hs-koblenz.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr \u00f6ffentliche Verwaltung und Finanzen Ludwigsburg","en":"University of Applied Sciences Ludwigsburg"},"org_id":"https://idp.hs-ludwigsburg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Magdeburg-Stendal","en":"Magdeburg-Stendal University of Applied Sciences"},"org_id":"https://idp.hs-magdeburg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Neubrandenburg","en":"Neubrandenburg University of Applied Sciences"},"org_id":"https://idp.hs-nb.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Pforzheim IdP","en":"Hochschule Pforzheim University IdP"},"org_id":"https://idp.hs-pforzheim.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule RheinMain","en":"Hochschule RheinMain"},"org_id":"https://idp.hs-rm.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Forstwirtschaft Rottenburg (HFR)","en":"University of Applied Forest Sciences Rottenburg"},"org_id":"https://idp.hs-rottenburg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Ruhr West","en":"Hochschule Ruhr West"},"org_id":"https://idp.hs-ruhrwest.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Schmalkalden","en":"Hochschule Schmalkalden"},"org_id":"https://idp.hs-schmalkalden.de/simplesaml","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Wismar","en":"Hochschule Wismar"},"org_id":"https://idp.hs-wismar.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Jade Hochschule","en":"Jade Hochschule"},"org_id":"https://idp.hs-woe.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Hamm-Lippstadt","en":"Hochschule Hamm-Lippstadt"},"org_id":"https://idp.hshl.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Zittau/G\u00f6rlitz","en":"Hochschule Zittau/Goerlitz"},"org_id":"https://idp.hszg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Aalen - Technik und Wirtschaft","en":"Hochschule Aalen - Technik und Wirtschaft"},"org_id":"https://idp.htw-aalen.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"HTWG Konstanz","en":"HTWG Konstanz"},"org_id":"https://idp.htwg-konstanz.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Technik und Wirtschaft des Saarlandes","en":"Hochschule f\u00fcr Technik und Wirtschaft des Saarlandes"},"org_id":"https://idp.htwsaar.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Wirtschaft und Gesellschaft Ludwigshafen","en":"Ludwigshafen University of Business and Society"},"org_id":"https://idp.hwg-lu.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Helmholtz-Zentrum Dresden-Rossendorf e.V. (HZDR)","en":"Helmholtz-Zentrum Dresden-Rossendorf e.V. (HZDR)"},"org_id":"https://idp.hzdr.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Leibniz-Institut f\u00fcr Atmosph\u00e4renphysik IAP","en":"Leibniz-Institute of Atmospheric Physics IAP"},"org_id":"https://idp.iap-kborn.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Leibniz-Institut f\u00fcr Deutsche Sprache (IDS)","en":"Leibniz-Institut f\u00fcr Deutsche Sprache (IDS)"},"org_id":"https://idp.ids-mannheim.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"IFW Dresden","en":"IFW Dresden"},"org_id":"https://idp.ifw-dresden.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Kiel Institut f\u00fcr Weltwirtschaft","en":"Kiel Institute for the world economy"},"org_id":"https://idp.ifw-kiel.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Leibniz-Institut f\u00fcr Plasmaforschung und Technologie e.V.","en":"Leibniz Institute for Plasma Science and Technology"},"org_id":"https://idp.inp-greifswald.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"IPB Halle","en":"IPB Halle"},"org_id":"https://idp.ipb-halle.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Internationale Psychoanalytische Universit\u00e4t Berlin (IPU)","en":"International Psychoanalytic University Berlin (IPU)"},"org_id":"https://idp.ipu-berlin.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Leibniz-Institut fuer Analytische Wissenschaften - ISAS - e.V.","en":"Leibniz-Institut fuer Analytische Wissenschaften - ISAS - e.V."},"org_id":"https://idp.isas.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"ISM International School of Management","en":"ISM International School of Management"},"org_id":"https://idp.ism.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Technische Universit\u00e4t Dortmund","en":"Technische Universit\u00e4t Dortmund"},"org_id":"https://idp.itmc.tu-dortmund.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Forschungszentrum J\u00fclich GmbH (FZJ)","en":"Forschungszentrum J\u00fclich GmbH (FZJ)"},"org_id":"https://idp.its.fz-juelich.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Leibniz-Institut f\u00fcr Wissensmedien","en":"Leibniz-Institut fuer Wissensmedien"},"org_id":"https://idp.iwm-tuebingen.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Kunsthochschule fuer Medien Koeln","en":"Academy of Media Arts Cologne"},"org_id":"https://idp.khm.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Katholische Stiftungsfachhochschule M\u00fcnchen","en":"Katholische Stiftungsfachhochschule M\u00fcnchen."},"org_id":"https://idp.ksfh.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Katholische Universit\u00e4t Eichst\u00e4tt-Ingolstadt","en":"Catholic University Eichstaett-Ingolstadt"},"org_id":"https://idp.ku.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Ministerium f\u00fcr Bildung, Wissenschaft und Kultur Mecklenburg-Vorpommern","en":"Ministry of Education, Science and Culture Mecklenburg-Vorpommern"},"org_id":"https://idp.kultus-mv.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Kunstakademie D\u00fcsseldorf","en":"Art Academy of Duesseldorf"},"org_id":"https://idp.kunstakademie-duesseldorf.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Leibniz-Rechenzentrum (LRZ)","en":"Leibniz Supercomputing Centre (LRZ)"},"org_id":"https://idp.lrz.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Mathematisches Forschungsinstitut Oberwolfach gGmbH","en":"Mathematisches Forschungsinstitut Oberwolfach gGmbH"},"org_id":"https://idp.mfo.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Staatliche Hochschule f\u00fcr Musik Trossingen","en":"Trossingen University of Music"},"org_id":"https://idp.mh-trossingen.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Max-Planck-Institut f\u00fcr Mathematik in den Naturwissenschaften","en":"Max Planck Institute for Mathematics in the Sciences"},"org_id":"https://idp.mis.mpg.de/simplesamlphp/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Max-Planck-Institut f\u00fcr Marine Mikrobiologie","en":"Max Planck Institute for Marine Microbiology"},"org_id":"https://idp.mpi-bremen.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Max-Planck-Institut f\u00fcr Informatik","en":"Max Planck Institute for Informatics"},"org_id":"https://idp.mpi-inf.mpg.de/mpii-idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Max-Planck-Institut f\u00fcr Softwaresysteme","en":"Max Planck Institute for Software Systems"},"org_id":"https://idp.mpi-sws.org/mpis-idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"NORDAKADEMIE Elmshorn","en":"NORDAKADEMIE Elmshorn"},"org_id":"https://idp.nordakademie.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Technische Hochschule N\u00fcrnberg Georg Simon Ohm","en":"Technische Hochschule N\u00fcrnberg Georg Simon Ohm"},"org_id":"https://idp.ohm-hochschule.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Ostbayerische Technische Hochschule Amberg-Weiden","en":"Ostbayerische Technische Hochschule Amberg-Weiden"},"org_id":"https://idp.oth-aw.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"PH Freiburg","en":"PH Freiburg"},"org_id":"https://idp.ph-freiburg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"PH Schw\u00e4bisch Gm\u00fcnd","en":"University of Education Gmuend"},"org_id":"https://idp.ph-gmuend.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"PH Karlsruhe","en":"University of Education Karlsruhe"},"org_id":"https://idp.ph-karlsruhe.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"PH Ludwigsburg","en":"PH Ludwigsburg"},"org_id":"https://idp.ph-ludwigsburg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"PH Weingarten","en":"PH Weingarten"},"org_id":"https://idp.ph-weingarten.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Reutlingen University / Hochschule Reutlingen","en":"Reutlingen University / Hochschule Reutlingen"},"org_id":"https://idp.reutlingen-university.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t zu K\u00f6ln","en":"Universit\u00e4t zu K\u00f6ln"},"org_id":"https://idp.rrz.uni-koeln.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Augsburg","en":"University of Augsburg"},"org_id":"https://idp.rz.uni-augsburg.de/simplesaml/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Otto-Friedrich-Universit\u00e4t Bamberg","en":"University of Bamberg"},"org_id":"https://idp.rz.uni-bamberg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Hohenheim","en":"University of Hohenheim"},"org_id":"https://idp.rz.uni-hohenheim.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Christian-Albrechts-Universit\u00e4t zu Kiel","en":"Christian-Albrechts-Universit\u00e4t zu Kiel"},"org_id":"https://idp.rz.uni-kiel.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"UniBw M\u00fcnchen","en":"UniBw Munich"},"org_id":"https://idp.rz.unibw-muenchen.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Karlsruher Institut f\u00fcr Technologie (KIT)","en":"Karlsruhe Institute of Technology (KIT)"},"org_id":"https://idp.scc.kit.edu/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Technische Hochschule Brandenburg","en":"University of Applied Sciences Brandenburg"},"org_id":"https://idp.th-brandenburg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Technische Hochschule Deggendorf","en":"Deggendorf Institute of Technology"},"org_id":"https://idp.th-deg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Technische Hochschule Mittelhessen","en":"Technische Hochschule Mittelhessen"},"org_id":"https://idp.thm.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Technische Universit\u00e4t Clausthal","en":"Technische Universit\u00e4t Clausthal"},"org_id":"https://idp.tu-clausthal.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Technische Universit\u00e4t Dresden","en":"Technische Universit\u00e4t Dresden"},"org_id":"https://idp.tu-dresden.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Technische Universit\u00e4t Ilmenau","en":"Technische Universit\u00e4t Ilmenau"},"org_id":"https://idp.tu-ilmenau.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Helmut-Schmidt-Universit\u00e4t Hamburg","en":"Helmut-Schmidt-Universit\u00e4t Hamburg"},"org_id":"https://idp.ub.hsu-hh.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t der K\u00fcnste Berlin","en":"The Berlin University of the Arts"},"org_id":"https://idp.udk-berlin.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Bayreuth","en":"University of Bayreuth"},"org_id":"https://idp.uni-bayreuth.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Bremen","en":"Universit\u00e4t Bremen"},"org_id":"https://idp.uni-bremen.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Heinrich-Heine-Universit\u00e4t D\u00fcsseldorf","en":"Heinrich Heine University Duesseldorf"},"org_id":"https://idp.uni-duesseldorf.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Duisburg-Essen","en":"Universit\u00e4t Duisburg-Essen"},"org_id":"https://idp.uni-duisburg-essen.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Europa-Universit\u00e4t Flensburg","en":"Europa-Universit\u00e4t Flensburg"},"org_id":"https://idp.uni-flensburg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Greifswald","en":"University of Greifswald"},"org_id":"https://idp.uni-greifswald.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Heidelberg","en":"Universit\u00e4t Heidelberg"},"org_id":"https://idp.uni-heidelberg.de","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Friedrich-Schiller-Universit\u00e4t Jena","en":"Friedrich-Schiller-Universitaet Jena"},"org_id":"https://idp.uni-jena.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"TU Kaiserslautern","en":"TU Kaiserslautern"},"org_id":"https://idp.uni-kl.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Konstanz","en":"University of Konstanz"},"org_id":"https://idp.uni-konstanz.de/shibboleth-idp","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t zu L\u00fcbeck","en":"University of Luebeck"},"org_id":"https://idp.uni-luebeck.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Mannheim","en":"University of Mannheim"},"org_id":"https://idp.uni-mannheim.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Oldenburg","en":"Universit\u00e4t Oldenburg"},"org_id":"https://idp.uni-oldenburg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Paderborn","en":"Paderborn University"},"org_id":"https://idp.uni-paderborn.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Potsdam","en":"University of Potsdam"},"org_id":"https://idp.uni-potsdam.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Rostock","en":"University of Rostock"},"org_id":"https://idp.uni-rostock.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Stuttgart","en":"University of Stuttgart"},"org_id":"https://idp.uni-stuttgart.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t T\u00fcbingen","en":"University of Tuebingen"},"org_id":"https://idp.uni-tuebingen.de/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Ulm","en":"Ulm University"},"org_id":"https://idp.uni-ulm.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Witten/Herdecke","en":"Witten/Herdecke University"},"org_id":"https://idp.uni-wh.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Bergische Universit\u00e4t Wuppertal","en":"University of Wuppertal"},"org_id":"https://idp.uni-wuppertal.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Virtuelle Hochschule Bayern (vhb)","en":"Virtual University of Bavaria (vhb)"},"org_id":"https://idp.vhb.org/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"W\u00fcrttembergische Landesbibliothek Stuttgart","en":"W\u00fcrttemberg State Library Stuttgart"},"org_id":"https://idp.wlb-stuttgart.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"ZBW - Leibniz-Informationszentrum Wirtschaft","en":"ZBW - Leibniz Information Centre for Economics"},"org_id":"https://idp.zbw.eu/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Zeppelin Universit\u00e4t","en":"Zeppelin University"},"org_id":"https://idp.zu.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"CISPA - Helmholtz-Zentrum f\u00fcr Informationssicherheit","en":"CISPA - Helmholtz Center for Information Security"},"org_id":"https://idp0.cispa.de/simplesaml/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t des Saarlandes","en":"Saarland University"},"org_id":"https://idp0.uni-saarland.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Leuphana - Universitaet Lueneburg","en":"Leuphana - University Lueneburg"},"org_id":"https://idp01.leuphana.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Technische Hochschule L\u00fcbeck","en":"Technische Hochschule L\u00fcbeck - University of Applied Sciences"},"org_id":"https://idp01.th-luebeck.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Fulda University of Applied Sciences","en":"Hochschule Fulda University of Applied Sciences"},"org_id":"https://idp1.rz.hs-fulda.de","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Technische Hochschule Ingolstadt","en":"Technische Hochschule Ingolstadt"},"org_id":"https://idp1.thi.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Helmholtz-Zentrum f\u00fcr Umweltforschung GmbH - UFZ IdP","en":"Helmholtz-Zentrum f\u00fcr Umweltforschung GmbH - UFZ IdP"},"org_id":"https://idp1.ufz.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"DIfE - Deutsches Institut f\u00fcr Ern\u00e4hrungsforschung","en":"DIfE - German Institute of Human Nutrition"},"org_id":"https://idp2.dife.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Augsburg","en":"University of Applied Sciences Augsburg"},"org_id":"https://idp2.hs-augsburg.de/simplesaml","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Furtwangen","en":"Furtwangen University"},"org_id":"https://idp2.hs-furtwangen.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Weihenstephan-Triesdorf.(IDP)","en":"Weihenstephan-Triesdorf university of applied sciences. (IDP)"},"org_id":"https://idp2.hswt.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Technik und Wirtschaft Dresden","en":"University of Applied Sciences Dresden"},"org_id":"https://idp2.htw-dresden.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Jacobs University Bremen gGmbH","en":"Jacobs University Bremen gGmbH"},"org_id":"https://idp2.jacobs-university.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Max Rubner-Institut (Neu)","en":"Max Rubner-Institute (Neu)"},"org_id":"https://idp2.maxrubner.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Rheinische Fachhochschule K\u00f6ln gGmbH","en":"Rheinische Fachhochschule K\u00f6ln gGmbH"},"org_id":"https://idp2.rfh-koeln.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"BA Dresden","en":"BA Dresden"},"org_id":"https://idp2.rz.ba-dresden.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Stiftung Tieraerztliche Hochschule Hannover (eduGAIN)","en":"University of Veterinary Medicine Hannover (eduGAIN)"},"org_id":"https://idp4.tiho-hannover.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Technische Hochschule Aschaffenburg","en":"Technische Hochschule Aschaffenburg"},"org_id":"https://idpc.th-ab.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"FH HRZ Darmstadt","en":"FH HRZ Darmstadt"},"org_id":"https://idpdomain.fhhrz.net/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"DIW Berlin Test Idp","en":"DIW Berlin Test Idp"},"org_id":"https://idptest.diw.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t M\u00fcnchen (LMU)","en":"University of Munich (LMU)"},"org_id":"https://lmuidp.lrz.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Berlin-Brandenburgische Akademie der Wissenschaften (BBAW)","en":"Berlin-Brandenburg Academy of Sciences and Humanities (BBAW)"},"org_id":"https://login.bbaw.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Beuth Hochschule f\u00fcr Technik Berlin","en":"Beuth University of Applied Sciences"},"org_id":"https://login.beuth-hochschule.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"DFNconf Login","en":"DFNconf Login"},"org_id":"https://login.conf.dfn.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"CrossAsia.org (VHO)","en":"CrossAsia.org (VHO)"},"org_id":"https://login.crossasia.org/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"DHBW Heidenheim","en":"DHBW Heidenheim"},"org_id":"https://login.dhbw-heidenheim.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"DHBW Ravensburg","en":"DHBW Ravensburg"},"org_id":"https://login.dhbw-ravensburg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"DIPF | Leibniz-Institut f\u00fcr Bildungsforschung und Bildungsinformation","en":"DIPF | Leibniz Institute for Research and Information in Education"},"org_id":"https://login.dipf.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"FernUniversit\u00e4t in Hagen","en":"University in Hagen"},"org_id":"https://login.fernuni-hagen.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Fachhochschule Aachen","en":"University of Applied Sciences Aachen"},"org_id":"https://login.fh-aachen.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Fachhochschule Bielefeld","en":"Fachhochschule Bielefeld"},"org_id":"https://login.fh-bielefeld.de/nidp/saml2/metadata","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Anmeldung Fachinformationsdienste (FID VHO)","en":"Anmeldung Fachinformationsdienste (FID VHO)"},"org_id":"https://login.fid-lizenzen.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Folkwang Universit\u00e4t der K\u00fcnste","en":"Folkwang University of the Arts"},"org_id":"https://login.folkwang-uni.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Angewandte Wissenschaften Hamburg","en":"Hamburg University of Applied Sciences"},"org_id":"https://login.haw-hamburg.de/nidp/saml2/metadata","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Musik und Theater Hamburg","en":"Hochschule fuer Musik und Theater Hamburg"},"org_id":"https://login.hfmt-hamburg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"HfWU N\u00fcrtingen-Geislingen","en":"HfWU Nuertingen-Geislingen"},"org_id":"https://login.hfwu.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Albstadt-Sigmaringen","en":"Albstadt-Sigmaringen University of Applied Sciences"},"org_id":"https://login.hs-albsig.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Mannheim","en":"University of Applied Sciences Mannheim"},"org_id":"https://login.hs-mannheim.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Technische Hochschule Ulm","en":"Technische Hochschule Ulm"},"org_id":"https://login.hs-ulm.de/shibboleth-idp","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Leibniz-Gemeinschaft - Gesch\u00e4ftsstelle","en":"Leibniz-Association - Headquarters"},"org_id":"https://login.leibniz-gemeinschaft.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"RWTH Aachen University","en":"RWTH Aachen University"},"org_id":"https://login.rz.rwth-aachen.de/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"SLUB Dresden","en":"SLUB Dresden"},"org_id":"https://login.slub-dresden.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Technische Hochschule Bingen","en":"Technische Hochschule Bingen"},"org_id":"https://login.th-bingen.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"TH K\u00f6ln (Technische Hochschule K\u00f6ln)","en":"TH K\u00f6ln (University of Applied Sciences)"},"org_id":"https://login.th-koeln.de/nidp/saml2/metadata","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Technische Hochschule Ostwestfalen-Lippe","en":"Technische Hochschule Ostwestfalen-Lippe"},"org_id":"https://login.th-owl.de/nidp/saml2/metadata","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Hamburg (UHH)","en":"Universit\u00e4t Hamburg (UHH)"},"org_id":"https://login.uni-hamburg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Siegen","en":"University of Siegen"},"org_id":"https://login.uni-siegen.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4tsklinikum Carl Gustav Carus Dresden","en":"University Hospital Carl Gustav Carus, Dresden"},"org_id":"https://login.uniklinikum-dresden.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Musik Detmold","en":"Detmold University of Music"},"org_id":"https://login.vrz-nrw.de/nidp/saml2/metadata","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Westf\u00e4lische Hochschule","en":"Westf\u00e4lische Hochschule, University of Applied Sciences"},"org_id":"https://login.w-hs.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Mittweida","en":"Hochschule Mittweida"},"org_id":"https://login4.hs-mittweida.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Staatliche Kunstsammlungen Dresden","en":"Staatliche Kunstsammlungen Dresden"},"org_id":"https://logon.skd.museum/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Arthistoricum.net - Fachinformationsdienst Kunst, Fotographie, Design","en":"Arthistoricum.net - Fachinformationsdienst Kunst, Fotographie, Design"},"org_id":"https://my.arthistoricum.net","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Propylaeum - Fachinformationsdienst Altertumswissenschaften","en":"Propylaeum - Specialized Information Service Classics"},"org_id":"https://my.propylaeum.de","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Albert-Ludwigs-Universit\u00e4t Freiburg","en":"Albert-Ludwigs-Universit\u00e4t Freiburg"},"org_id":"https://mylogin.uni-freiburg.de/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Filmuniversit\u00e4t Babelsberg KONRAD WOLF","en":"Filmuniversity Babelsberg KONRAD WOLF"},"org_id":"https://new.filmuniversitaet.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Max Planck Institut fuer chemische Oekologie","en":"Max Planck Institute for Chemical Ecology"},"org_id":"https://radius.ice.mpg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"DAAD-ID","en":"DAAD ID"},"org_id":"https://saml.daad.de/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"DHBW Stuttgart","en":"DHBW Stuttgart"},"org_id":"https://saml.dhbw-stuttgart.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Leibniz Institut f\u00fcr Naturstoff-Forschung und Infektionsbiologie, Hans-Kn\u00f6ll-Institut","en":"Leibniz Institut f\u00fcr Naturstoff-Forschung und Infektionsbiologie, Hans-Kn\u00f6ll-Institut"},"org_id":"https://saml.hki-jena.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule M\u00fcnchen (HM)","en":"University of Applied Sciences Munich (HM)"},"org_id":"https://shi-idp2.rz.fh-muenchen.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Geisenheim University","en":"Hochschule Geisenheim University"},"org_id":"https://shib-idp-srv1.hs-gm.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Alfred-Wegener-Institut, Helmholtz-Zentrum f\u00fcr Polar- und Meeresforschung (AWI)","en":"Alfred Wegener Institute, Helmholtz Centre for Polar and Marine Research (AWI)"},"org_id":"https://shib-idp.awi.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Humboldt-Universit\u00e4t zu Berlin","en":"Humboldt-Universit\u00e4t zu Berlin"},"org_id":"https://shib-idp.cms.hu-berlin.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Bildende K\u00fcnste Braunschweig","en":"Braunschweig University of Art"},"org_id":"https://shib-idp.hbk-bs.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Osnabr\u00fcck","en":"Hochschule Osnabr\u00fcck"},"org_id":"https://shib-idp.hs-osnabrueck.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Ostfalia","en":"Ostfalia"},"org_id":"https://shib-idp.ostfalia.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Hildesheim","en":"Universit\u00e4t Hildesheim"},"org_id":"https://shib-idp.uni-hildesheim.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Osnabr\u00fcck","en":"Universit\u00e4t Osnabr\u00fcck"},"org_id":"https://shib-idp.uni-osnabrueck.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Commerzbibliothek Hamburg","en":"Commerzbibliothek Hamburg"},"org_id":"https://shib.hk24.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Martin-Luther-Universit\u00e4t Halle-Wittenberg","en":"Martin-Luther-University Halle-Wittenberg"},"org_id":"https://shib.itz.uni-halle.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"P\u00e4dagogische Hochschule Heidelberg","en":"P\u00e4dagogische Hochschule Heidelberg"},"org_id":"https://shib.ph-heidelberg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"TU Hamburg (TUHH)","en":"Hamburg University of Technology (TUHH)"},"org_id":"https://shib.rz.tu-harburg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Mainz","en":"University of Mainz"},"org_id":"https://shib.uni-mainz.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Technik, Wirtschaft und Kultur Leipzig","en":"Hochschule f\u00fcr Technik, Wirtschaft und Kultur Leipzig"},"org_id":"https://shib1.rz.htwk-leipzig.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Ravensburg-Weingarten","en":"University of Applied Sciences Ravensburg Weingarten"},"org_id":"https://shibb-idp.hs-weingarten.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Max Planck Institut f\u00fcr Plasmaphysik (IPP)","en":"Max Planck Institute for Plasma Physics (IPP)"},"org_id":"https://shibb.mpcdf.mpg.de/ipp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Max Planck Computing and Data Facility (MPCDF)","en":"Max Planck Computing and Data Facility (MPCDF)"},"org_id":"https://shibb.mpcdf.mpg.de/mpcdf/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Max Planck Institut f\u00fcr Quantenoptik (MPQ)","en":"Max Planck Institute for Quantum Optics (MPQ)"},"org_id":"https://shibb.mpcdf.mpg.de/mpq/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"ZALF M\u00fcncheberg IdP","en":"ZALF M\u00fcncheberg IdP"},"org_id":"https://shibb.zalf.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Musik Weimar","en":"Hochschule f\u00fcr Musik Weimar"},"org_id":"https://shibbo.hfm-weimar.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Bauhaus-Universit\u00e4t Weimar","en":"Bauhaus-Universit\u00e4t Weimar"},"org_id":"https://shibbo.scc.uni-weimar.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Gesellschaft f\u00fcr wissenschaftliche Datenverarbeitung mbH G\u00f6ttingen","en":"Gesellschaft f\u00fcr wissenschaftliche Datenverarbeitung mbH G\u00f6ttingen"},"org_id":"https://shibboleth-idp.gwdg.de/gwdg/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschulbibliothekszentrum NRW (hbz) - Identit\u00e4tserbringung (IdP)","en":"Hochschulbibliothekszentrum NRW (hbz) - Identity Provider (IdP)"},"org_id":"https://shibboleth-idp.hbz-nrw.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Max-Planck Institute (im MetaDir der GWDG)","en":"Max-Planck Institutes (in MetaDir of GWDG)"},"org_id":"https://shibboleth-idp.mpg.de/mpg/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4tsklinikum Wuerzburg","en":"Wuerzburg University Hospital"},"org_id":"https://shibboleth-idp.ukw.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Georg-August Universit\u00e4t G\u00f6ttingen","en":"Georg-August University G\u00f6ttingen"},"org_id":"https://shibboleth-idp.uni-goettingen.de/uni/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Regensburg","en":"University of Regensburg"},"org_id":"https://shibboleth-idp.uni-regensburg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t W\u00fcrzburg","en":"University of Wuerzburg"},"org_id":"https://shibboleth-idp.uni-wuerzburg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"DHBW Karlsruhe","en":"DHBW Karlsruhe"},"org_id":"https://shibboleth.dhbw-karlsruhe.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Kaiserslautern","en":"University of Applied Science Kaiserslautern"},"org_id":"https://shibboleth.hs-kl.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Medizinische Hochschule Hannover","en":"Hannover Medical School"},"org_id":"https://shibboleth.mh-hannover.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Bielefeld","en":"University of Bielefeld"},"org_id":"https://shibboleth.uni-bielefeld.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Bonn","en":"Universit\u00e4t Bonn"},"org_id":"https://shibboleth.uni-bonn.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Trier","en":"Trier University"},"org_id":"https://shibboleth.uni-trier.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Vechta","en":"University of Vechta"},"org_id":"https://shibboleth.uni-vechta.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"WHU - Otto Beisheim School of Management","en":"WHU - Otto Beisheim School of Management"},"org_id":"https://shibboleth.whu.edu/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Max Planck Institut fuer Kohlenforschung","en":"Max Planck Institut fuer Kohlenforschung"},"org_id":"https://shibboleth1.mpi-muelheim.mpg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Technik Stuttgart","en":"Hochschule f\u00fcr Technik Stuttgart"},"org_id":"https://shibboleth1.rz.hft-stuttgart.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Koblenz-Landau","en":"University Koblenz-Landau"},"org_id":"https://shibboleth2.uni-koblenz.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Nordhausen","en":"University of Applied Sciences Nordhausen"},"org_id":"https://shibweb1.hs-nordhausen.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Erfurt","en":"University of Erfurt"},"org_id":"https://sinope.uni-erfurt.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Mainz","en":"Hochschule Mainz"},"org_id":"https://srv-idp-001.fh-mainz.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Leibniz-Institut f\u00fcr Katalyse e.V. (LIKAT)","en":"Leibniz Institute for Catalysis (LIKAT)"},"org_id":"https://srv-idp.catalysis.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Bundesinstitut f\u00fcr Arzneimittel und Medizinprodukte","en":"Federal Institute for Drugs and Medical Devices"},"org_id":"https://sso.bfarm.de:8443/auth/realms/DFNConf","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Deutsche Sporthochschule K\u00f6ln","en":"German Sport University Cologne"},"org_id":"https://sso.dshs-koeln.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Darmstadt, University of Applied Sciences","en":"Hochschule Darmstadt, University of Applied Sciences"},"org_id":"https://sso.h-da.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Musik N\u00fcrnberg","en":"College of Music Nuremberg"},"org_id":"https://sso.hfm-nuernberg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Philosophie M\u00fcnchen","en":"Hochschule f\u00fcr Philosophie M\u00fcnchen"},"org_id":"https://sso.hfph.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"HMTM IdP","en":"HMTM IdP"},"org_id":"https://sso.hmtm.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Rhein-Waal","en":"Rhine-Waal University of Applied Sciences"},"org_id":"https://sso.hochschule-rhein-waal.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Neu-Ulm","en":"University of Applied Sciences Neu-Ulm"},"org_id":"https://sso.hs-neu-ulm.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Ostbayerische Technische Hochschule Regensburg","en":"Ostbayerische Technische Hochschule Regensburg"},"org_id":"https://sso.hs-regensburg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Leibniz Universit\u00e4t Hannover","en":"Leibniz Universit\u00e4t Hannover"},"org_id":"https://sso.idm.uni-hannover.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Max-Planck-Institut f\u00fcr Chemie","en":"Max-Planck-Institute for Chemistry"},"org_id":"https://sso.mpic.de/auth/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"TU Braunschweig","en":"TU Braunschweig"},"org_id":"https://sso.tu-bs.de","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Passau","en":"University Of Passau"},"org_id":"https://sso.uni-passau.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Zuse Institut Berlin","en":"Zuse Institute Berlin"},"org_id":"https://sso.zib.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Worms","en":"Hochschule Worms"},"org_id":"https://ssoserver.hs-worms.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"MfN - Berlin","en":"MfN - Berlin"},"org_id":"https://sts.windows.net/dad5f964-5709-42c9-8188-c5b0deac3547/","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule Niederrhein IdP","en":"Hochschule Niederrhein IdP"},"org_id":"https://themis.hs-niederrhein.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Technische Universit\u00e4t M\u00fcnchen (TUM)","en":"Technical University of Munich (TUM)"},"org_id":"https://tumidp.lrz.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Hochschule f\u00fcr Technik und Wirtschaft - HTW Berlin","en":"Hochschule f\u00fcr Technik und Wirtschaft - HTW Berlin"},"org_id":"https://weblogin.htw-berlin.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Philipps-Universit\u00e4t Marburg","en":"Philipps-Universit\u00e4t Marburg"},"org_id":"https://weblogin.uni-marburg.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Wests\u00e4chsische Hochschule Zwickau","en":"Wests\u00e4chsische Hochschule Zwickau"},"org_id":"https://whzidp.fh-zwickau.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"TU Chemnitz","en":"TU Chemnitz"},"org_id":"https://wtc.tu-chemnitz.de/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Meta-Videoportal unterrichtsvideos.net","en":"Meta-Videoportal unterrichtsvideos.net"},"org_id":"https://wwuvidp.uni-muenster.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"APOLLON Hochschule Bremen","en":"APOLLON Hochschule Bremen"},"org_id":"https://www.apollon-campus.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"BTU Cottbus - Senftenberg","en":"BTU Cottbus - Senftenberg"},"org_id":"https://www.b-tu.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"San-Netz.de","en":"San-Netz.de"},"org_id":"https://www.san-netz.de","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t Erlangen-N\u00fcrnberg (FAU)","en":"Universit\u00e4t Erlangen-N\u00fcrnberg (FAU)"},"org_id":"https://www.sso.uni-erlangen.de/simplesaml/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Technische Universit\u00e4t N\u00fcrnberg","en":"University of Technology Nuremberg"},"org_id":"https://www.sso.utn.de/simplesaml/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"VHO Einzelnutzer Nationallizenzen","en":"VHO Einzelnutzer Nationallizenzen"},"org_id":"https://www.vho.de/idpnl","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Verbundzentrale des GBV (VZG)","en":"Verbundzentrale des GBV (VZG)"},"org_id":"https://www.vho.de/idpvzg","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Leibniz-Forschungsinstitut f\u00fcr Molekulare Pharmakologie - FMP (XAAI1 IdP)","en":"Leibniz-Forschungsinstitut f\u00fcr Molekulare Pharmakologie - FMP (XAAI1 IdP)"},"org_id":"https://xaai1.fmp-berlin.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"Universit\u00e4t M\u00fcnster","en":"Universit\u00e4t M\u00fcnster"},"org_id":"https://zividp.uni-muenster.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"de":"DFnconf Zoom SSO","en":"DFnconf Zoom SSO"},"org_id":"https://zoom-sso.conf.dfn.de/idp/shibboleth","secure_internet_home":"https://eduvpn1.eduvpn.de/"},{"display_name":{"en":"Pembelajaran Abad Ke-21"},"org_id":"https://sso.pak21.my/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.myren.net.my/"},{"display_name":{"en":"Universiti Malaysia Terengganu"},"org_id":"https://idp3.umt.edu.my/idp/shibboleth","secure_internet_home":"https://eduvpn.myren.net.my/"},{"display_name":{"en":"Malaysian Research and Education Network (MYREN)"},"org_id":"https://sso.myren.net.my/idp/shibboleth","secure_internet_home":"https://eduvpn.myren.net.my/"},{"display_name":{"en":"International Medical University"},"org_id":"https://idp.imu.edu.my/idp/shibboleth","secure_internet_home":"https://eduvpn.myren.net.my/"},{"display_name":{"en":"Universiti Tun Hussein Onn"},"org_id":"https://sifulan.uthm.edu.my/idp/shibboleth","secure_internet_home":"https://eduvpn.myren.net.my/"},{"display_name":{"en":"Universiti Sultan Zainal Abidin"},"org_id":"https://sso.unisza.edu.my/idp/shibboleth","secure_internet_home":"https://eduvpn.myren.net.my/"},{"display_name":{"en":"Universiti Malaysia Sabah"},"org_id":"https://umsidp.ums.edu.my/idp/shibboleth","secure_internet_home":"https://eduvpn.myren.net.my/"},{"display_name":{"en":"Universiti Putra Malaysia"},"org_id":"https://idf.upm.edu.my/idp/shibboleth","secure_internet_home":"https://eduvpn.myren.net.my/"},{"display_name":{"en":"SIFULAN Virtual Home"},"org_id":"https://vho.sifulan.my/idp/shibboleth","secure_internet_home":"https://eduvpn.myren.net.my/"},{"display_name":{"en":"Perdana University"},"org_id":"https://sso.perdanauniversity.edu.my/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.myren.net.my/"},{"display_name":{"en":"Institut Pendidikan Guru Kampus Bahasa Antarabangsa"},"org_id":"https://kba.ipgm.e-id.my/idp/shibboleth","secure_internet_home":"https://eduvpn.myren.net.my/"},{"display_name":{"en":"Institut Pendidikan Guru Kampus Darulaman"},"org_id":"https://kda.ipgm.e-id.my/idp/shibboleth","secure_internet_home":"https://eduvpn.myren.net.my/"},{"display_name":{"en":"Politeknik Sultan Salahuddin Abdul Aziz Shah"},"org_id":"https://psa.mypolycc.e-id.my/idp/shibboleth","secure_internet_home":"https://eduvpn.myren.net.my/"},{"display_name":{"en":"Politeknik METrO Kuala Lumpur"},"org_id":"https://pmkl.mypolycc.e-id.my/idp/shibboleth","secure_internet_home":"https://eduvpn.myren.net.my/"},{"display_name":{"en":"Kolej Komuniti Kuala Langat"},"org_id":"https://kkkl.mypolycc.e-id.my/idp/shibboleth","secure_internet_home":"https://eduvpn.myren.net.my/"},{"display_name":{"en":"Ministry of Higher Education"},"org_id":"https://idp.mohe.e-id.my/idp/shibboleth","secure_internet_home":"https://eduvpn.myren.net.my/"},{"display_name":{"en":"Universiti Tunku Abdul Rahman"},"org_id":"https://sifulan.utar.edu.my/idp/shibboleth","secure_internet_home":"https://eduvpn.myren.net.my/"},{"display_name":{"en":"Universiti Pertahanan Nasional Malaysia"},"org_id":"https://shib-idp.upnm.edu.my/idp/shibboleth","secure_internet_home":"https://eduvpn.myren.net.my/"},{"display_name":{"en":"Universiti Sains Malaysia"},"org_id":"https://shibsso.usm.my/idp/shibboleth","secure_internet_home":"https://eduvpn.myren.net.my/"},{"display_name":{"en":"Universiti Malaysia Pahang"},"org_id":"https://idp.ump.edu.my/sso/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.myren.net.my/"},{"display_name":{"en":"Universiti Sains Islam Malaysia"},"org_id":"https://shib-idp.usim.edu.my/idp/shibboleth","secure_internet_home":"https://eduvpn.myren.net.my/"},{"display_name":{"en":"CNRST"},"org_id":"https://idp.cnrst.ma/idp/shibboleth","secure_internet_home":"https://eduvpn.marwan.ma/"},{"display_name":{"en":"MARWAN"},"org_id":"https://idp.marwan.ma/idp/shibboleth","secure_internet_home":"https://eduvpn.marwan.ma/"},{"display_name":{"en":"ENIM"},"org_id":"https://idp-server.enim.ac.ma/idp/shibboleth","secure_internet_home":"https://eduvpn.marwan.ma/"},{"display_name":{"en":"UIT"},"org_id":"https://idp.uit.ac.ma/idp/shibboleth","secure_internet_home":"https://eduvpn.marwan.ma/"},{"display_name":{"en":"USMS"},"org_id":"https://fid.usms.ac.ma/idp/shibboleth","secure_internet_home":"https://eduvpn.marwan.ma/"},{"display_name":{"en":"UM5"},"org_id":"https://idp.um5.ac.ma/idp/shibboleth","secure_internet_home":"https://eduvpn.marwan.ma/"},{"display_name":{"no":"Agder fylkeskommune"},"org_id":"agderfk.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"no":"Akademiet Realfagsskole Oslo"},"org_id":"feide.oslo.realfag.akademiet.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Akademiet utdanning Norge AS","nn":"Akademiet utdanning Noreg AS","no":"Akademiet utdanning Norge AS"},"org_id":"feide.akademiet.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Alstahaug municipality","nn":"Alstahaug kommune","no":"Alstahaug kommune"},"org_id":"alstahaug.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Alta municipality","nn":"Alta kommune","no":"Alta kommune"},"org_id":"skoler.alta.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Alvdal municipality","nn":"Alvdal kommune","no":"Alvdal kommune"},"org_id":"alvdal.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"And\u00f8y municipality","no":"And\u00f8y kommune"},"org_id":"andoy.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Ansgar University College","no":"Ansgar h\u00f8yskole"},"org_id":"ansgarhogskole.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Aremark municipality","nn":"Aremark kommune","no":"Aremark kommune"},"org_id":"aremark.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Arendal municipality","nn":"Arendal kommune","no":"Arendal kommune"},"org_id":"arendal.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"The Oslo School of Architecture and Design","nn":"Arkitektur- og designh\u00f8gskulen i Oslo","no":"Arkitektur- og designh\u00f8gskolen i Oslo"},"org_id":"aho.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Asker municipality","nn":"Asker kommune","no":"Asker kommune"},"org_id":"asker.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Askvoll municipality","nn":"Askvoll kommune","no":"Askvoll kommune"},"org_id":"askvoll.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Aukra municipality","nn":"Aukra kommune","no":"Aukra kommune"},"org_id":"feide.aukra.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Aure municipality","nn":"Aure kommune","no":"Aure kommune"},"org_id":"aure.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Aurland municipality","nn":"Aurland kommune","no":"Aurland kommune"},"org_id":"aurland.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Aurskog-H\u00f8land municipality","nn":"Aurskog-H\u00f8land kommune","no":"Aurskog-H\u00f8land kommune"},"org_id":"feide.ahk.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Austevoll municipality","nn":"Austevoll kommune","no":"Austevoll kommune"},"org_id":"austevoll.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Austrheim municipality","nn":"Austrheim kommune","no":"Austrheim kommune"},"org_id":"austrheim.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Aver\u00f8y municipality","nn":"Aver\u00f8y kommune","no":"Aver\u00f8y kommune"},"org_id":"averoy.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Balsfjord municipality","nn":"Balsfjord kommune","no":"Balsfjord kommune"},"org_id":"balsfjord.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Bamble municipality","nn":"Bamble kommune","no":"Bamble kommune"},"org_id":"bamble.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Bardu municipality","nn":"Bardu kommune","no":"Bardu kommune"},"org_id":"bardu.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Beiarn municipality","nn":"Beiarn kommune","no":"Beiarn kommune"},"org_id":"beiarn.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Bergen municipality","nn":"Bergen kommune","no":"Bergen kommune"},"org_id":"bergensskolen.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Bergen Kristne Grunnskole","nn":"Bergen Kristne Grunnskole","no":"Bergen Kristne Grunnskole"},"org_id":"bkgs.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Berlev\u00e5g municipality","nn":"Berlev\u00e5g kommune","no":"Berlev\u00e5g kommune"},"org_id":"berlevag.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"no":"Bindal kommune"},"org_id":"bindal.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Bindalseidet school","nn":"Bindalseidet skule SA","no":"Bindalseidet skole SA"},"org_id":"bindalseidet.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Birkenes municipality","nn":"Birkenes kommune","no":"Birkenes kommune"},"org_id":"birkenes.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Bjerkreim municipality","nn":"Bjerkreim kommune","no":"Bjerkreim kommune"},"org_id":"bjerkreim.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Blue Cross Norway,","nn":"Bl\u00e5 Kors Skole","no":"Bl\u00e5 Kors Skole"},"org_id":"blakors.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Bod\u00f8 municipality","nn":"Bod\u00f8 kommune","no":"Bod\u00f8 kommune"},"org_id":"bodo.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Bokn municipality","nn":"Bokn kommune","no":"Bokn kommune"},"org_id":"bokn.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Bremanger municipality","nn":"Bremanger kommune","no":"Bremanger kommune"},"org_id":"bremanger.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Br\u00f8nn\u00f8y municipality","nn":"Br\u00f8nn\u00f8y kommune","no":"Br\u00f8nn\u00f8y kommune"},"org_id":"bronnoy.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Bygland municipality","nn":"Bygland kommune","no":"Bygland kommune"},"org_id":"bygland.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Bykle municipality","nn":"Bykle kommune","no":"Bykle kommune"},"org_id":"bykle.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"B\u00e6rum municipality","nn":"B\u00e6rum kommune","no":"B\u00e6rum kommune"},"org_id":"baerum.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"B\u00f8 municipality - Nordland","nn":"B\u00f8 kommune - Nordland","no":"B\u00f8 kommune - Nordland"},"org_id":"boe.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"B\u00f8mlo municipality","nn":"B\u00f8mlo kommune","no":"B\u00f8mlo kommune"},"org_id":"bomlo.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"B\u00e5tsfjord municipality","nn":"B\u00e5tsfjord kommune","no":"B\u00e5tsfjord kommune"},"org_id":"batsfjord.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Chr. Michelsen Institute","nn":"Chr. Michelsens Institutt","no":"Chr. Michelsens Institutt"},"org_id":"cmi.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Danielsen High School","nn":"Danielsen Vidareg\u00e5ande Skole","no":"Danielsen Videreg\u00e5ende Skole"},"org_id":"danielsen-skoler.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"no":"Den norske skolen i Brussel"},"org_id":"dnsb.be","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Norwegian School Malaga","nn":"Den norske skulen i Malaga","no":"Den norske skolen i Malaga"},"org_id":"dnsmalaga.com","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Norwegian Centre for International Cooperation in Education","nn":"Direktoratet for internasjonalisering og kvalitetsutvikling i h\u00f8yere utdanning","no":"Direktoratet for internasjonalisering og kvalitetsutvikling i h\u00f8yere utdanning"},"org_id":"diku.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Dovre municipality","nn":"Dovre kommune","no":"Dovre kommune"},"org_id":"dovreskulane.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Drammen municipality","nn":"Drammen kommune","no":"Drammen kommune"},"org_id":"drammen.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"no":"Drangedal kommune"},"org_id":"drangedal.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Queen Maud University College","nn":"Dronning Mauds Minne H\u00f8gskule","no":"Dronning Mauds Minne H\u00f8gskole"},"org_id":"dmmh.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"no":"Drottningborg vgs AS"},"org_id":"drottningborg.vgs.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"no":"Dyr\u00f8y Kommune"},"org_id":"dyroy.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"D\u00f8nna municipality","nn":"D\u00f8nna kommune","no":"D\u00f8nna kommune"},"org_id":"donna.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Eidfjord municipality","nn":"Eidfjord kommune","no":"Eidfjord kommune"},"org_id":"eidfjord.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Eidskog municipality","nn":"Eidskog kommune","no":"Eidskog kommune"},"org_id":"eidskog.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Eidsvoll municipality","nn":"Eidsvoll kommune","no":"Eidsvoll kommune"},"org_id":"eidsvoll.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Eigersund municipality","nn":"Eigersund kommune","no":"Eigersund kommune"},"org_id":"eigersund.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Ekrehagen school","nn":"Ekrehagen skole","no":"Ekrehagen skole"},"org_id":"ekrehagen.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Feide","no":"Feide"},"org_id":"feide.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Fjellhaug International University College","nn":"Fjellhaug Internasjonale H\u00f8gskule","no":"Fjellhaug Internasjonale H\u00f8gskole"},"org_id":"fjellhaug.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Norwegian Defence University College","nn":"Forsvarets h\u00f8gskuler","no":"Forsvarets h\u00f8gskoler"},"org_id":"mil.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Oslo Christian Center","nn":"Grunnskolen Oslo Kristne Senter","no":"Grunnskolen Oslo Kristne Senter"},"org_id":"oks.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"BI Norwegian Business School","nn":"Handelsh\u00f8yskolen BI","no":"Handelsh\u00f8yskolen BI"},"org_id":"bi.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Hustadvika municipality","no":"Hustadvika kommune"},"org_id":"hustadvika.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Inland Norway University of Applied Sciences","no":"H\u00f8gskolen i Innlandet"},"org_id":"inn.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Molde University College","nn":"H\u00f8gskulen i Molde","se":"Molde Allaskuvla","no":"H\u00f8gskolen i Molde"},"org_id":"himolde.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"\u00d8stfold University College","nn":"H\u00f8gskulen i \u00d8stfold","se":"\u00d8stfold Allaskuvla","no":"H\u00f8gskolen i \u00d8stfold"},"org_id":"hiof.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Volda University College","nn":"H\u00f8gskulen i Volda","se":"Volda Allaskuvla","no":"H\u00f8gskulen i Volda"},"org_id":"hivolda.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Western Norway University of Applied Sciences","nn":"H\u00f8gskulen p\u00e5 Vestlandet","no":"H\u00f8gskulen p\u00e5 Vestlandet"},"org_id":"hvl.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Kristiania University College","nn":"H\u00f8yskolen Kristiania","no":"H\u00f8yskolen Kristiania"},"org_id":"feide.egms.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"no":"Kristen Friskole AS"},"org_id":"kfskolen.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"no":"Kristen videreg\u00e5ende skole Tr\u00f8ndelag"},"org_id":"kvt.vgs.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Oslo National Academy of the Arts","nn":"Kunsth\u00f8gskulen i Oslo","no":"Kunsth\u00f8gskolen i Oslo"},"org_id":"khio.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"KVN High School","nn":"KVN videreg\u00e5ande skule","no":"KVN videreg\u00e5ende skole"},"org_id":"kvn.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Lovisenberg diaconal university college","nn":"Lovisenberg diakonale h\u00f8gskule","no":"Lovisenberg diakonale h\u00f8gskole"},"org_id":"ldh.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"no":"Lukas videreg\u00e5ende skole"},"org_id":"lukas.vgs.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"MF Norwegian School of Theology, Religion and Society","nn":"MF vitenskapelig h\u00f8yskole","no":"MF vitenskapelig h\u00f8yskole"},"org_id":"mf.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"NLA University College","nn":"NLA H\u00f8gskolen","se":"NLA H\u00f8gskolen","no":"NLA H\u00f8gskolen"},"org_id":"nla.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Nord University","nn":"Nord universitet","no":"Nord universitet"},"org_id":"nord.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Norwegian School of Economics","nn":"Norges Handelsh\u00f8yskole","no":"Norges Handelsh\u00f8yskole"},"org_id":"nhh.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Norwegian School of Sport Sciences","nn":"Noregs idrettsh\u00f8gskule","no":"Norges idrettsh\u00f8gskole"},"org_id":"nih.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Norwegian University of Life Sciences","nn":"Noregs milj\u00f8- og biovitenskapelige universitet","no":"Norges milj\u00f8- og biovitenskapelige universitet"},"org_id":"nmbu.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Norwegian Academy of Music","nn":"Noregs musikkh\u00f8gskule","no":"Norges musikkh\u00f8gskole"},"org_id":"nmh.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"no":"Norges Realfagsgymnas Ungdomsskole B\u00e6rum"},"org_id":"nrg.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"NTNU","no":"NTNU"},"org_id":"ntnu.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"New \u00d8rland municipality","no":"Nye \u00d8rland kommune"},"org_id":"feide.orland.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"OsloMet \u2013 Oslo Metropolitan University","nn":"OsloMet \u2013 storbyuniversitetet","se":"OsloMet \u2013 stuorrag\u00e1vpotuniversitehta","no":"OsloMet \u2013 storbyuniversitetet"},"org_id":"oslomet.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"The Norwegian Police University College","nn":"Politih\u00f8gskulen","no":"Politih\u00f8gskolen"},"org_id":"phs.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"R\u00f8ros municipality","nn":"R\u00f8ros kommune","no":"R\u00f8ros kommune"},"org_id":"feide.roros.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"S\u00e1mi allaskuvla \u2013 S\u00e1mi University College","nn":"S\u00e1mi allaskuvla \u2013 Samisk h\u00f8gskule","se":"S\u00e1mi allaskuvla \u2013 Samisk h\u00f8gskole","no":"S\u00e1mi allaskuvla \u2013 Samisk h\u00f8gskole"},"org_id":"samas.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"S\u00e1mi High School and Reindeer Husbandry school","nn":"Samisk Videreg\u00e5ande Skule og reindriftsskule","se":"S\u00e1mi joatkkaskuvla ja boazodoalloskuvla","no":"Samisk videreg\u00e5ende skole og reindriftsskole"},"org_id":"samisk.vgs.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Stad municipality","no":"Stad kommune"},"org_id":"stad.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"St. Paul's Catholic School","nn":"St. Paul skule","no":"St. Paul skole"},"org_id":"stpaul.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"no":"St. Sunniva skole"},"org_id":"feide.stsunniva.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Service Provider","no":"Tjenesteleverand\u00f8r"},"org_id":"spusers.feide.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"UiT The Arctic University of Norway","nn":"UiT Noregs arktiske universitet","se":"UiT Norgga \u00e1rktala\u0161 universitehta","no":"UiT Norges arktiske universitet"},"org_id":"uit.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Uninett AS","no":"Uninett AS"},"org_id":"uninett.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"University of Agder","nn":"Universitetet i Agder","se":"Agder Universitehta","no":"Universitetet i Agder"},"org_id":"uia.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"University of Bergen","nn":"Universitetet i Bergen","se":"Bergen Universitehta","no":"Universitetet i Bergen"},"org_id":"uib.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"University of Oslo","nn":"Universitetet i Oslo","se":"Oslo Universitehta","no":"Universitetet i Oslo"},"org_id":"uio.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"University of Stavanger","nn":"Universitetet i Stavanger","se":"Stavanger Universitehta","no":"Universitetet i Stavanger"},"org_id":"uis.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"University of South-Eastern Norway","nn":"Universitetet i S\u00f8raust-Noreg","no":"Universitetet i S\u00f8r\u00f8st-Norge"},"org_id":"usn.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"The University Center in Svalbard","no":"Universitetssenteret p\u00e5 Svalbard"},"org_id":"unis.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"VID Specialized University","nn":"VID vitenskapelige h\u00f8gskule","no":"VID vitenskapelige h\u00f8gskole"},"org_id":"vid.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"\u00c5snes municipality","nn":"\u00c5snes kommune","no":"\u00c5snes kommune"},"org_id":"asnes.kommune.no","secure_internet_home":"https://guest.eduvpn.no/"},{"display_name":{"en":"Pakistan Education & Research Network"},"org_id":"https://idp.pern.edu.pk/idp/shibboleth","secure_internet_home":"https://vpn.pern.edu.pk/","keyword_list":{"en":"PERN-IdP"}},{"display_name":{"en":"Bahria University Pakistan"},"org_id":"https://idp.bahria.edu.pk/idp/shibboleth","secure_internet_home":"https://vpn.pern.edu.pk/","keyword_list":{"en":"Bahria University Pakistan"}},{"display_name":{"en":"NED University of Engineering and Technology Pakistan"},"org_id":"https://idp.neduet.edu.pk/idp/shibboleth","secure_internet_home":"https://vpn.pern.edu.pk/","keyword_list":{"en":"NED University of Engineering and Technology Pakistan"}},{"display_name":{"en":"PERN IdP Pakistan"},"org_id":"https://idp2.pern.edu.pk/idp/shibboleth","secure_internet_home":"https://vpn.pern.edu.pk/","keyword_list":{"en":"PERN IdP Pakistan"}},{"display_name":{"en":"University of Sargodha Pakistan"},"org_id":"https://idp.uos.edu.pk/idp/shibboleth","secure_internet_home":"https://vpn.pern.edu.pk/","keyword_list":{"en":"University of Sargodha Pakistan"}},{"display_name":{"en":"The Islamia University of Bahawalpur, Pakistan"},"org_id":"https://idp.iub.edu.pk/idp/shibboleth","secure_internet_home":"https://vpn.pern.edu.pk/","keyword_list":{"en":"IUB"}},{"display_name":{"en":"HEC Pakistan"},"org_id":"https://idp.hec.gov.pk/idp/shibboleth","secure_internet_home":"https://vpn.pern.edu.pk/","keyword_list":{"en":"HEC Pakistan"}},{"display_name":{"en":"University of KwaZulu-Natal","zu":"inYuvesi yaKwaZulu-Natali","af":"Universiteit van KwaZulu-Natal"},"org_id":"http://proxy.safire.ac.za/birk.php/federation.ukzn.ac.za/adfs/services/trust","secure_internet_home":"https://guest.eduvpn.ac.za/"},{"display_name":{"en":"University of the Western Cape","af":"Universiteit van Wes-Kaapland"},"org_id":"https://proxy.safire.ac.za/birk.php/saml.uwc.ac.za/simplesaml/saml2/idp/metadata.php","secure_internet_home":"https://guest.eduvpn.ac.za/"},{"display_name":{"en":"Walter Sisulu University","af":"Walter Sisulu Universiteit"},"org_id":"https://proxy.safire.ac.za/birk.php/idp.wsu.ac.za/simplesaml/saml2/idp/metadata.php","secure_internet_home":"https://guest.eduvpn.ac.za/"},{"display_name":{"en":"University of Venda"},"org_id":"https://proxy.safire.ac.za/birk.php/sts.windows.net/f38ba9d8-554c-48a2-ae42-13b1e7f3c797/","secure_internet_home":"https://guest.eduvpn.ac.za/"},{"display_name":{"en":"SANReN Competency Area"},"org_id":"https://proxy.safire.ac.za/birk.php/googleidp.sanren.ac.za/simplesaml/saml2/idp/metadata.php","secure_internet_home":"https://guest.eduvpn.ac.za/"},{"display_name":{"en":"Rhodes University","xh":"IYunivesiti iRhodes","af":"Rhodes-universiteit"},"org_id":"https://proxy.safire.ac.za/birk.php/login.ru.ac.za/idp/shibboleth","secure_internet_home":"https://guest.eduvpn.ac.za/"},{"display_name":{"en":"University of Pretoria","af":"Universiteit van Pretoria"},"org_id":"https://proxy.safire.ac.za/birk.php/www1.up.ac.za:443/oam/fed","secure_internet_home":"https://guest.eduvpn.ac.za/"},{"display_name":{"en":"Cape Peninsula University of Technology - Staff","af":"Kaapse Skiereiland Universiteit van Tegnologie - Personeel"},"org_id":"https://proxy.safire.ac.za/birk.php/sts.windows.net/90bb22db-a73a-4971-b7d6-7ca3ef90cf06/","secure_internet_home":"https://guest.eduvpn.ac.za/"},{"display_name":{"en":"Sol Plaatje University"},"org_id":"https://proxy.safire.ac.za/birk.php/sts.windows.net/acbcaed8-7adc-460c-ba57-028bdc80d84a/","secure_internet_home":"https://guest.eduvpn.ac.za/"},{"display_name":{"en":"Central University of Technology, Free State"},"org_id":"http://proxy.safire.ac.za/birk.php/logon.cut.ac.za/adfs/services/trust","secure_internet_home":"https://guest.eduvpn.ac.za/"},{"display_name":{"en":"University of Fort Hare"},"org_id":"http://proxy.safire.ac.za/birk.php/federate.ufh.ac.za/adfs/services/trust","secure_internet_home":"https://guest.eduvpn.ac.za/"},{"display_name":{"en":"University of Cape Town","af":"Universiteit Kaapstad","xh":"IYunivesithi yaseKapa"},"org_id":"https://proxy.safire.ac.za/birk.php/srvslsfed001.uct.ac.za/simplesaml/saml2/idp/metadata.php","secure_internet_home":"https://guest.eduvpn.ac.za/"},{"display_name":{"en":"CSIR","af":"WNNR"},"org_id":"https://proxy.safire.ac.za/birk.php/idp.csir.co.za/simplesamlphp/saml2/idp/metadata.php","secure_internet_home":"https://guest.eduvpn.ac.za/"},{"display_name":{"en":"Tshwane University of Technology"},"org_id":"http://proxy.safire.ac.za/birk.php/tutfs.tut.ac.za/adfs/services/trust","secure_internet_home":"https://guest.eduvpn.ac.za/"},{"display_name":{"en":"University of the Free State"},"org_id":"http://proxy.safire.ac.za/birk.php/safire.ufs.ac.za/adfs/services/trust","secure_internet_home":"https://guest.eduvpn.ac.za/"},{"display_name":{"en":"Wits University","af":"Wits Universiteit","zu":"Wits Yunivesithi","st":"Yunivesithi ya Wits"},"org_id":"https://proxy.safire.ac.za/birk.php/idp.wits.ac.za/safss/saml2/idp/metadata.php","secure_internet_home":"https://guest.eduvpn.ac.za/"},{"display_name":{"en":"North-West University","tn":"Yunibesiti Ya Bokone-Bophirima","af":"Noordwes Universiteit"},"org_id":"https://proxy.safire.ac.za/birk.php/shib.nwu.ac.za/idp/shibboleth","secure_internet_home":"https://guest.eduvpn.ac.za/"},{"display_name":{"en":"Vaal University of Technology - Staff (VUT)"},"org_id":"http://proxy.safire.ac.za/birk.php/sso.vut.ac.za/adfs/services/trust","secure_internet_home":"https://guest.eduvpn.ac.za/"},{"display_name":{"en":"TENET South Africa","af":"TENET Suid-Afrika"},"org_id":"https://proxy.safire.ac.za/birk.php/idp-01.tenet.ac.za/idp/shibboleth","secure_internet_home":"https://guest.eduvpn.ac.za/"},{"display_name":{"en":"South African Theological Seminary","af":"Suid-Afrikaanse Teologiese Seminarium","fr":"S\u00e9minaire Th\u00e9ologique Sud-Africain","pt":"Semin\u00e1rio Teol\u00f3gico Sul Africano","xh":"ISouth African Theological Seminary","es":"Seminario Teologico Sudafricano"},"org_id":"https://proxy.safire.ac.za/birk.php/sso.sats.edu.za/","secure_internet_home":"https://guest.eduvpn.ac.za/"},{"display_name":{"en":"SAFIRE Test Identity Provider","zu":"I-SAFIRE Umhlinzeki Kamazisi Wokuhlola","xh":"I-SAFIRE Umboneleli Wesazisi Sovavanyo","af":"SAFIRE Toets Identiteit-Verskaffer","st":"SAFIRE Mofani wa Boitsebiso ba Teko"},"org_id":"https://proxy.safire.ac.za/birk.php/testidp.safire.ac.za/simplesaml/saml2/idp/metadata.php","secure_internet_home":"https://guest.eduvpn.ac.za/"},{"display_name":{"en":"Cape Peninsula University of Technology - Students","af":"Kaapse Skiereiland Universiteit van Tegnologie - Studente"},"org_id":"https://proxy.safire.ac.za/birk.php/sts.windows.net/cc6148eb-d356-4f38-900f-3a4d62b954c8/","secure_internet_home":"https://guest.eduvpn.ac.za/"},{"display_name":{"en":"Nelson Mandela University (NMMU)"},"org_id":"https://proxy.safire.ac.za/birk.php/nmmusaml-sc1.nmmu.ac.za/simplesaml/saml2/idp/metadata.php","secure_internet_home":"https://guest.eduvpn.ac.za/"},{"display_name":{"en":"Stellenbosch University","xh":"iYunivesithi Stellenbosch","af":"Universiteit Stellenbosch"},"org_id":"http://proxy.safire.ac.za/birk.php/federate.sun.ac.za/adfs/services/trust","secure_internet_home":"https://guest.eduvpn.ac.za/"},{"display_name":{"en":"eduID Sri Lanka"},"org_id":"https://idp.eduid.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"learn, eduid, lka, sri lanka, lanka"}},{"display_name":{"en":"Sabaragamuwa University of Sri Lanka"},"org_id":"https://idp.sab.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"university"}},{"display_name":{"en":"Faculty of Engineering, University of Jaffna"},"org_id":"https://idp.eng.jfn.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/"},{"display_name":{"en":"Ampara ATI"},"org_id":"https://idp.ampara.sliate.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"University"}},{"display_name":{"en":"Vavuniya Campus of the University of Jaffna"},"org_id":"https://idp.vau.jfn.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/"},{"display_name":{"en":"University of the Visual and Performing Arts"},"org_id":"https://iam.vpa.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"UVPA"}},{"display_name":{"en":"Wayamba University of Sri Lanka - Kuliyapitiya Premises"},"org_id":"https://idpserver.wyb.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"university research"}},{"display_name":{"en":"Sri Lanka Institute of Advanced Technological Educaiton"},"org_id":"https://idp.sliate.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"sliate,ati"}},{"display_name":{"en":"University of Vocational Technology"},"org_id":"https://idp.univotec.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"university"}},{"display_name":{"en":"Institute of Biochemistry, Molecular Biology and Biotechnology"},"org_id":"https://idp.ibmbb.cmb.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"Molecular Biology, Molecular Life Sciences, Research, Education"}},{"display_name":{"en":"ICHEMC IDP"},"org_id":"https://idp.ichemc.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"university"}},{"display_name":{"en":"Wayamba University of Sri Lanka - Makandura Premises"},"org_id":"https://idp.mkd.wyb.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"University"}},{"display_name":{"en":"Ministry of Higher Education - Sri Lanka"},"org_id":"https://idp.mohe.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"Ministry of Higher Education - Sri Lanka"}},{"display_name":{"en":"tech test"},"org_id":"https://techtest.learn.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"tech test"}},{"display_name":{"en":"University of Vavuniya"},"org_id":"https://idp.vau.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"vau.ac.lk"}},{"display_name":{"en":"National Institute of Education"},"org_id":"https://idp.nie.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"nie,niemaharagama,education,niesrilanka"}},{"display_name":{"en":"Gampaha Wickramarchchi University Of Indigenous Medicine"},"org_id":"https://iam.gwu.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"web,GWUIM , Gampaha Wickramarachchi University of Indigenous Medicine"}},{"display_name":{"en":"Faculty of Medicine, University of Ruhuna"},"org_id":"https://idp.medi.ruh.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"university, research"}},{"display_name":{"en":"University of Colombo School of Computing"},"org_id":"https://idp.ucsc.cmb.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"ucsc"}},{"display_name":{"en":"ATI - Jaffna, SLIATE"},"org_id":"https://idp.jaffna.sliate.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"University\nSLIATE\nATI Jaffna"}},{"display_name":{"en":"Advanced Technological Institute Batticaloa"},"org_id":"https://idp.batticaloa.sliate.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/"},{"display_name":{"en":"Uva Wellassa University"},"org_id":"https://idp.uwu.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"uwu"}},{"display_name":{"en":"University of Kelaniya - Sri Lanka"},"org_id":"https://idp.kln.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"UOK, IDP, Identity Access Federation,"}},{"display_name":{"en":"Faculty of Engineering, University of Ruhuna"},"org_id":"https://shiboidp.eng.ruh.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"university"}},{"display_name":{"en":"Postgraduate Institute of Science"},"org_id":"https://idp.pgis.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"Postgraduate, Masters, MPhil, PhD"}},{"display_name":{"en":"Swami Vipulananda Institute of Aesthetic Studies(SVIAS),EUSL"},"org_id":"https://idp.svias.esn.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"esn, eastern"}},{"display_name":{"en":"University of Moratuwa"},"org_id":"https://idp.uom.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"edugain\nuom\ncites\neduroam\nidp"}},{"display_name":{"en":"University of Colombo, Sri Lanka"},"org_id":"https://idp.cmb.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"eduroam, research, university"}},{"display_name":{"en":"University of Peradeniya"},"org_id":"https://idp.pdn.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"UoP"}},{"display_name":{"en":"Trincomalee Campus, EUSL"},"org_id":"https://idp.tc.esn.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"University,TCEUSL,Trincomalee Campus"}},{"display_name":{"en":"South Eastern University of Sri Lanka"},"org_id":"https://idp.seu.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"seu, oluvil"}},{"display_name":{"en":"The Open University of Sri Lanka"},"org_id":"https://ims.ou.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"Open University"}},{"display_name":{"en":"NERD Centre"},"org_id":"https://idp.nerdc.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"engineering, research and development"}},{"display_name":{"en":"Postgraduate Institute of Agriculture"},"org_id":"https://idp.pgia.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"university"}},{"display_name":{"en":"Institute of Indigenous Medicine University of Colombo Rajagiriya"},"org_id":"https://idp.iim.cmb.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"Indigenous Medicine,Ayurveda"}},{"display_name":{"en":"Industrial Technology Institute - Sri Lanka"},"org_id":"https://idp.iti.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"Research or Development"}},{"display_name":{"en":"University of Ruhuna (Wellamadama Site)"},"org_id":"https://idp.ruh.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"university, research"}},{"display_name":{"en":"Sri Lanka Technological Campus"},"org_id":"https://idp.sltc.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"university"}},{"display_name":{"en":"LEARN - Sri Lanka"},"org_id":"https://idp.learn.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"LEARN, LK, staff"}},{"display_name":{"en":"University of Jaffna"},"org_id":"https://idp.jfn.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"university or research"}},{"display_name":{"en":"Buddhist and Pali University of Sri Lanka"},"org_id":"https://idp.bpu.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"university"}},{"display_name":{"en":"Kotelawala Defence University"},"org_id":"https://idp.kdu.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"kdu"}},{"display_name":{"en":"University of Sri Jayewardenepura"},"org_id":"https://idp.sjp.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"sjp"}},{"display_name":{"en":"University of Ruhuna"},"org_id":"https://idp.wel.ruh.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"University"}},{"display_name":{"en":"Faculty of Agriculture, University of Ruhuna"},"org_id":"https://samanala.agri.ruh.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/"},{"display_name":{"en":"Gampaha Wickramarachchi Ayurveda Institute, University of Kelaniya"},"org_id":"https://iam.gwai.kln.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"University, GWAI, KLN"}},{"display_name":{"en":"Arthur C Clarke Institute for Modern Technologies"},"org_id":"https://idp.accmt.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"accimt"}},{"display_name":{"en":"Advanced Technological Institute_Kegalle IDP"},"org_id":"https://idp.kegalle.sliate.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"SLIATE ATI Kegalle"}},{"display_name":{"en":"Eastern University Sri Lanka"},"org_id":"https://idp.esn.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"Eastern University, Research"}},{"display_name":{"en":"Rajarata University of Sri Lanka"},"org_id":"https://telambu.rjt.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/"},{"display_name":{"en":"Faculty of Technology, University of Ruhuna, Sri Lanka"},"org_id":"https://idp.tec.ruh.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"IDP, TEC, RUH, technology, ruhuna"}},{"display_name":{"en":"Institute of Technology, University of Moratuwa"},"org_id":"https://idp.itum.mrt.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"ITUM\nedugain\nuom\ncites\neduroam\nidp"}},{"display_name":{"en":"Sri Lanka-German Training Institute"},"org_id":"https://idp.slgti.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"vocational training"}},{"display_name":{"en":"University Grants Commission - Sri Lanka"},"org_id":"https://idp.ugc.ac.lk/idp/shibboleth","secure_internet_home":"https://eduvpn.ac.lk/","keyword_list":{"en":"ugc"}},{"display_name":{"nl":"Universiteit Leiden","en":"Leiden University"},"org_id":"https://login.uaccess.leidenuniv.nl/nidp/saml2/metadata","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"universiteit leiden leiden university leidenuniv rul","nl":"universiteit leiden leiden university leidenuniv rul"}},{"display_name":{"nl":"Nikhef","en":"Nikhef"},"org_id":"https://sso.nikhef.nl/sso/saml2/idp/metadata.php","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"national institute subatomic physics Nikhef Research","nl":"nationaal instituut subatomaire fysica Nikhef Research"}},{"display_name":{"nl":"Rijn IJssel","en":"Rijn IJssel"},"org_id":"http://fed.rijnijssel.nl/adfs/services/trust","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"Rijn IJssel ROC MBO","nl":"Rijn IJssel ROC MBO"}},{"display_name":{"nl":"Trimbos Instituut","en":"Trimbos Instituut"},"org_id":"http://federatie.trimbos.nl/adfs/services/trust","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"Trimbos Instituut","nl":"Trimbos Instituut"}},{"display_name":{"nl":"Hogeschool voor de Kunsten Utrecht","en":"Utrecht School of the Arts"},"org_id":"https://federatie.hku.nl","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"Utrecht School of the Arts HBO hku","nl":"Utrecht School of the Arts HBO hku"}},{"display_name":{"nl":"Radboud Universiteit","en":"Radboud University"},"org_id":"https://conext.authenticatie.ru.nl/simplesaml/saml2/idp/metadata.php","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"university nijmegen ru","nl":"universiteit nijmegen ru"}},{"display_name":{"nl":"Vrije Universiteit Amsterdam","en":"Vrije Universiteit Amsterdam"},"org_id":"http://stsfed.login.vu.nl/adfs/services/trust","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"VU Vrije Universiteit Amsterdam","nl":"VU Vrije Universiteit Amsterdam"}},{"display_name":{"nl":"Drenthe College","en":"Drenthe College"},"org_id":"http://sts.drenthecollege.nl/adfs/services/trust","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"Cummunity College Drenthe ROC DC Drenthe College DrentheCollege","nl":"Drenthe College ROC DC DrentheCollege"}},{"display_name":{"nl":"Naturalis Biodiversity Center","en":"Naturalis Biodiversity Center"},"org_id":"http://adfs.naturalis.nl/adfs/services/trust","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"Naturalis Biodiversity Center","nl":"Naturalis Biodiversity Center"}},{"display_name":{"nl":"SURFnet bv","en":"SURFnet bv"},"org_id":"https://idp.surfnet.nl","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"SURFnet bv SURF konijn surf surfnet powered by","nl":"SURFnet bv SURF konijn powered by"}},{"display_name":{"nl":"G\u00c9ANT Staff Identity Provider","en":"G\u00c9ANT Staff Identity Provider"},"org_id":"https://idp.geant.org","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"G\u00c9ANT staff IdP Identity provider geant","nl":"G\u00c9ANT staff IdP Identity provider geant"}},{"display_name":{"nl":"STC-Group","en":"STC-Group"},"org_id":"http://sts.stc-r.nl/adfs/services/trust","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"STC Opleiding Scheepvaart","nl":"STC Opleiding Scheepvaart"}},{"display_name":{"nl":"Friesland College","en":"Friesland College"},"org_id":"http://fs.fcroc.nl/adfs/services/trust","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"Friesland College","nl":"Friesland College"}},{"display_name":{"nl":"SOMT University (Stichting Opleidingen Musculoskeletale Therapie)","en":"SOMT University (Stichting Opleidingen Musculoskeletale Therapie)"},"org_id":"https://sts.somtuniversity.nl/adfs/services/trust","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"SOMT University (Stichting Opleidingen Musculoskeletale Therapie)","nl":"SOMT University (Stichting Opleidingen Musculoskeletale Therapie)"}},{"display_name":{"nl":"Stichting EGI","en":"EGI Foundation"},"org_id":"https://sso.egi.eu/edugainidp/shibboleth","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"EGI Foundation","nl":"EGI Foundation"}},{"display_name":{"nl":"Summa College","en":"Summa College"},"org_id":"http://adfs-p.summacollege.nl/adfs/services/trust","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"Summa College","nl":"Summa College"}},{"display_name":{"nl":"Wellantcollege","en":"Wellantcollege"},"org_id":"http://sts.wellant.nl/adfs/services/trust","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"wellantcollege wellant college","nl":"wellantcollege wellant college"}},{"display_name":{"nl":"Hogeschool Saxion","en":"Saxion University of Applied Sciences"},"org_id":"http://login.saxion.nl/adfs/services/trust","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"saxion university of applied sciences saxion hogeschool","nl":"saxion university of applied sciences saxion hogeschool"}},{"display_name":{"nl":"Stichting Nuffic","en":"Stichting Nuffic"},"org_id":"https://sts.windows.net/0b883569-39c0-4403-a6a9-ed60f81be9e5/","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"nuffic ep unesco","nl":"nuffic ep unesco"}},{"display_name":{"nl":"Prinses M\u00e1xima Centrum","en":"Prinses M\u00e1xima Centrum"},"org_id":"http://idpv3.hierinloggen.nl/adfs/services/trust","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"Prinses M\u00e1xima Maxima Centrum kinderoncologie Utrecht PMC","nl":"Prinses M\u00e1xima Maxima Centrum kinderoncologie Utrecht PMC"}},{"display_name":{"nl":"Hogeschool Utrecht","en":"Hogeschool Utrecht"},"org_id":"https://sts.hu.nl/adfs/services/trust","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"hogeschool hu hogeschoolutrecht hu university of applied sciences hogeschool utrecht hbo","nl":"hogeschool hu hogeschoolutrecht hu university of applied sciences hogeschool utrecht hbo"}},{"display_name":{"nl":"Rijksinstituut voor Volksgezondheid en Milieu","en":"National Institute for Public Health and the Environment"},"org_id":"http://fs.rivm.nl/adfs/services/trust","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"rivm health environment rijk","nl":"rivm volk gezondheid milieu rijk"}},{"display_name":{"nl":"SaNS Expertisecentrum","en":"SaNS Expertisecentrum"},"org_id":"https://sts.windows.net/8171367b-3418-48da-a7bb-9dc1d300c5e8/","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"sans samenwerking nieuw sis expertise","nl":"sans samenwerking nieuw sis expertise"}},{"display_name":{"nl":"SURF (Nieuw)","en":"SURF (New)"},"org_id":"http://login.surf.nl/adfs/services/trust","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"SURF powered by surfnet surfmarket surfsara surf-bureau co\u00f6peratie cooperatie surffoundation bv konijn 1surf","nl":"SURF powered by surfnet surfmarket surfsara surf-bureau co\u00f6peratie cooperatie surffoundation bv konijn 1surf"}},{"display_name":{"nl":"Koninklijke Bibliotheek","en":"Koninklijke Bibliotheek"},"org_id":"https://sts.windows.net/01ef09a2-c608-4fc7-af66-836e50ddde2c/","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"Koninklijke Bibliotheek kb","nl":"Koninklijke Bibliotheek kb"}},{"display_name":{"nl":"Universiteit Twente","en":"University of Twente"},"org_id":"https://sts.windows.net/723246a1-c3f5-43c5-acdc-43adb404ac4d/","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"University of Twente Universiteit Twente ut utwente","nl":"University of Twente Universiteit Twente ut utwente"}},{"display_name":{"nl":"Stichting Studielink","en":"Studielink"},"org_id":"https://sts.windows.net/5f5e8caa-c291-4c93-879f-af63ceeac809/","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"studielink","nl":"studielink"}},{"display_name":{"nl":"Avans Hogeschool","en":"Avans University of Applied Sciences"},"org_id":"https://sts.windows.net/87c50b58-2ef2-423d-a4db-1fa7c84efcfa/","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"avans university of applied sciences avans hogeschool","nl":"avans hogeschool avans university of applied sciences"}},{"display_name":{"nl":"Koninklijke Nederlandse Akademie van Wetenschappen (KNAW)","en":"Koninklijke Nederlandse Akademie van Wetenschappen (KNAW)"},"org_id":"http://adfs.knaw.nl/adfs/services/trust","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"knaw bureau academie","nl":"knaw bureau academie"}},{"display_name":{"nl":"ROC Mondriaan","en":"ROC Mondriaan"},"org_id":"https://sts.windows.net/b3f1b7b8-2918-4c5d-8d58-7c3241c605d4/","secure_internet_home":"https://nl.eduvpn.org/","keyword_list":{"en":"ROC Mondriaan MBO Den Haag Zuid Holland","nl":"ROC Mondriaan International Business Hotel Management"}},{"display_name":{"en":"eduroam Visitor Access","nl":"eduroam Visitor Access"},"org_id":"https://eva-saml-idp.eduroam.nl/simplesamlphp/saml2/idp/metadata.php","secure_internet_home":"https://nl.eduvpn.org/"},{"display_name":{"en":"Research and Education Network for Uganda"},"org_id":"https://idp.renu.ac.ug/shibboleth","secure_internet_home":"https://eduvpn.renu.ac.ug/"},{"display_name":{"en":"ICER - Uganda"},"org_id":"https://login.iceruganda.org/idp/shibboleth","secure_internet_home":"https://eduvpn.renu.ac.ug/"},{"display_name":{"en":"Infectious Diseases Institute"},"org_id":"https://idp.idi.co.ug/shibboleth","secure_internet_home":"https://eduvpn.renu.ac.ug/"},{"display_name":{"en":"Uganda Christian University"},"org_id":"https://idp.ucu.ac.ug/shibboleth","secure_internet_home":"https://eduvpn.renu.ac.ug/"},{"display_name":{"en":"Rakai Health Sciences Program"},"org_id":"https://login.rhsp.org/idp/shibboleth","secure_internet_home":"https://eduvpn.renu.ac.ug/"},{"display_name":{"en":"Uganda Virus Research Institute (UVRI)"},"org_id":"https://idp.uvri.go.ug/shibboleth","secure_internet_home":"https://eduvpn.renu.ac.ug/"},{"display_name":{"en":"Uganda Martyrs Hospital Lubaga"},"org_id":"https://idp.lubagahospital.org/idp/shibboleth","secure_internet_home":"https://eduvpn.renu.ac.ug/"},{"display_name":{"en":"African Center of Excellence in Bioinformatics - Uganda"},"org_id":"https://login.ace.ac.ug/idp/shibboleth","secure_internet_home":"https://eduvpn.renu.ac.ug/"},{"display_name":{"en":"Bishop Stuart University"},"org_id":"https://idp.bsu.ac.ug/idp/shibboleth","secure_internet_home":"https://eduvpn.renu.ac.ug/"},{"display_name":{"en":"Mengo Hospital"},"org_id":"https://idp.mengohospital.org/idp/shibboleth","secure_internet_home":"https://eduvpn.renu.ac.ug/"},{"display_name":{"en":"URAN Association IdP","ru":"\u0410\u0441\u0441\u043e\u0446\u0438\u0430\u0446\u0438\u044f \u0423\u0420\u0410\u041d IdP"},"org_id":"https://idp.uran.ua/idp/shibboleth","secure_internet_home":"https://eduvpn.uran.ua/"},{"display_name":{"en":"Borys Grinchenko Kyiv University"},"org_id":"https://idp.kubg.edu.ua/simplesaml/saml2/idp/metadata.php","secure_internet_home":"https://eduvpn.uran.ua/"}]}
\ No newline at end of file diff --git a/test_data/real/organization_list-1.json.pure.minisig b/test_data/real/organization_list-1.json.pure.minisig deleted file mode 100644 index 629bcbb..0000000 --- a/test_data/real/organization_list-1.json.pure.minisig +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: signature from minisign secret key -RWRtBSX1alxyGReKo8QufuktuIkU/oXJbNAyZlsMzMkgpJMg51ggFxzGu637jTTUxcwsekQ7T5fve+1uZN928JwLkuH9yjJs+wQ= -trusted comment: timestamp:1636532257 file:organization_list.json -M4BxKPHmxhG06zV/FmM4XGqlIjKCSffaEAjFtk4sMCKkGK36raGX1nwj95eRXbauoR+LtMNZVDy6Z0G/eQbBBw== diff --git a/test_data/real/server_list-1.json b/test_data/real/server_list-1.json deleted file mode 100644 index 13a390d..0000000 --- a/test_data/real/server_list-1.json +++ /dev/null @@ -1 +0,0 @@ -{"v":1636532223,"server_list":[{"base_url":"https://eduvpn.rash.al/","country_code":"AL","public_key_list":["Xv3l24gbMX8NtTnFQbWO2fGKPwKuc6EbjQDv8qw2GVk"],"server_type":"secure_internet","support_contact":["mailto:helpdesk@rash.al"]},{"base_url":"https://eduvpn.cynet.ac.cy/","country_code":"CY","public_key_list":["plmxbtNEQcmUhXNElL90cuh1mg60tgMl9szk0_eEVSI"],"server_type":"secure_internet","support_contact":["mailto:eduvpnsupport@cynet.ac.cy"]},{"base_url":"https://eduvpn.deic.dk/","country_code":"DK","public_key_list":["bRTz33KIuYo_w_-AbzNtdmLDqIm11_eGiHXQniojxY4"],"server_type":"secure_internet","support_contact":["mailto:eduvpn@deic.dk"]},{"base_url":"https://eduvpn.eenet.ee/","country_code":"EE","public_key_list":["jGpivOdwCRoLlexYKQjulZPPP4s3d9SVBFslI6RroAo"],"server_type":"secure_internet","support_contact":["mailto:eduvpn@eenet.ee"]},{"authentication_url_template":"https://eduvpn1.funet.fi/Shibboleth.sso/Login?entityID=@ORG_ID@&target=@RETURN_TO@","base_url":"https://eduvpn1.funet.fi/","country_code":"FI","public_key_list":["H4NTnM18BJgU_B3r8OBDVblBSfozB2Zu97I_ag2whmM"],"server_type":"secure_internet","support_contact":["mailto:eduvpn@csc.fi"]},{"authentication_url_template":"https://eduvpn-poc.renater.fr/Shibboleth.sso/Login?entityID=@ORG_ID@&target=@RETURN_TO@","base_url":"https://eduvpn-poc.renater.fr/","country_code":"FR","public_key_list":["ePVNzE15h0yS6Xf3s8nJWmc8V6FeFziA3TZr0uOacFg"],"server_type":"secure_internet","support_contact":["https://assistance.renater.fr/"]},{"authentication_url_template":"https://eduvpn1.eduvpn.de/saml/login?ReturnTo=@RETURN_TO@&IdP=@ORG_ID@","base_url":"https://eduvpn1.eduvpn.de/","country_code":"DE","public_key_list":["QjJHMit3vhHwLKi-fu2dXXSxMxnkskFVS3hMwyCnWQs"],"server_type":"secure_internet","support_contact":["mailto:eduvpn@dfn.de","tel:+49308842999120"]},{"authentication_url_template":"https://eduvpn.myren.net.my/Shibboleth.sso/Login?entityID=@ORG_ID@&target=@RETURN_TO@","base_url":"https://eduvpn.myren.net.my/","country_code":"MY","public_key_list":["2WsUQpiUofRZ9IWZ8qQaOeQG4-RMy981QguOEMg4-e4"],"server_type":"secure_internet","support_contact":["mailto:helpdesk@myren.net.my"]},{"authentication_url_template":"https://eduvpn.marwan.ma/saml/login?ReturnTo=@RETURN_TO@&IdP=@ORG_ID@","base_url":"https://eduvpn.marwan.ma/","country_code":"MA","public_key_list":["aX-El_yRPdcUDF5S2smQ-9U7BzB35_1RtFYSjbHfEz8"],"server_type":"secure_internet","support_contact":["mailto:eduvpn-support@marwan.ma","tel:+212700062200"]},{"base_url":"https://sram.eduvpn.nl/","display_name":"SURF Research Access Management","keyword_list":"sram","server_type":"institute_access","support_contact":["mailto:eduvpn@surf.nl"]},{"base_url":"https://guest.eduvpn.no/","country_code":"NO","public_key_list":["qOLCcqXWZm9nmjsrwiJQxxWD606vDEJ2MIcc85oJmnE"],"server_type":"secure_internet","support_contact":["mailto:kontakt@uninett.no"]},{"authentication_url_template":"https://vpn.pern.edu.pk/Shibboleth.sso/Login?entityID=@ORG_ID@&target=@RETURN_TO@","base_url":"https://vpn.pern.edu.pk/","country_code":"PK","public_key_list":["LKWFZblpTFvFDY4E_0tnD8yHpK-iOSrJop_1x-A4cQ8"],"server_type":"secure_internet","support_contact":["mailto:eduvpn@pern.edu.pk"]},{"authentication_url_template":"https://guest.eduvpn.ac.za/Shibboleth.sso/Login?entityID=@ORG_ID@&target=@RETURN_TO@","base_url":"https://guest.eduvpn.ac.za/","country_code":"ZA","public_key_list":["juqJG81DBCpGwwK999FjSDqSUJ_Zw7mpVdR5Fhsa1RI"],"server_type":"secure_internet","support_contact":["https://www.tenet.ac.za/services/eduvpn"]},{"authentication_url_template":"https://eduvpn.ac.lk/Shibboleth.sso/Login?entityID=@ORG_ID@&target=@RETURN_TO@","base_url":"https://eduvpn.ac.lk/","country_code":"LK","public_key_list":["drq4-3Sg35UJHxVfx-ssR3onjHihCVH-zjXYPnEfudI"],"server_type":"secure_internet","support_contact":["mailto:eduvpn@learn.ac.lk"]},{"authentication_url_template":"https://nl.eduvpn.org/php-saml-sp/login?ReturnTo=@RETURN_TO@&IdP=@ORG_ID@","base_url":"https://nl.eduvpn.org/","country_code":"NL","public_key_list":["O53DTgB956magGaWpVCKtdKIMYqywS3FMAC5fHXdFNg"],"server_type":"secure_internet","support_contact":["mailto:eduvpn@surf.nl"]},{"authentication_url_template":"https://eduvpn.renu.ac.ug/Shibboleth.sso/Login?entityID=@ORG_ID@&target=@RETURN_TO@","base_url":"https://eduvpn.renu.ac.ug/","country_code":"UG","public_key_list":["4plEYRW26amB1-PcRRxWcKlEcDXsUO4yNHnf0VA2MPE"],"server_type":"secure_internet","support_contact":["mailto:technical@renu.ac.ug","tel:+256783979515"]},{"authentication_url_template":"https://eduvpn.uran.ua/saml/login?ReturnTo=@RETURN_TO@&IdP=@ORG_ID@","base_url":"https://eduvpn.uran.ua/","country_code":"UA","public_key_list":["gCUDsmSIn0pVPc4C-QNLsBil6WxkwDDwxfvTC262p9U"],"server_type":"secure_internet","support_contact":["mailto:dopomoga@uran.ua","tel:+380442049816"]},{"base_url":"https://eduvpn.ulm.ac.id/","display_name":"Universitas Lambung Mangkurat","server_type":"institute_access","support_contact":["mailto:frobby@ulm.ac.id","tel:+625113305195"]},{"base_url":"https://avans.eduvpn.nl/","display_name":"Avans Hogeschool","keyword_list":"avans university of applied sciences hogeschool","server_type":"institute_access","support_contact":["mailto:servicepunt@avans.nl","https://servicepunt.avans.nl/"]},{"base_url":"https://eduvpn.cic.userena.cl/","display_name":{"en":"University of La Serena","es":"Universidad de La Serena"},"server_type":"institute_access","support_contact":["mailto:soporte@userena.cl","https://soporte.cic.userena.cl/","tel:+56512334622"]},{"base_url":"https://eduvpn.uv.cl/","display_name":{"en":"University of Valparaiso","es":"Universidad de Valpara\u00edso"},"server_type":"institute_access","support_contact":["mailto:eduvpn@uv.cl","tel:+56995437860","https://dtic.uv.cl/"]},{"base_url":"https://eduvpn.uitm.edu.my/","display_name":"Universiti Teknologi MARA","keyword_list":"uitm","server_type":"institute_access","support_contact":["mailto:network@uitm.edu.my"]},{"base_url":"https://sunset.nuonet.fr/","display_name":"CNOUS","server_type":"institute_access","support_contact":["mailto:support-technique-nuo@listes.nuonet.fr"]},{"base_url":"https://vpn.cnrst.ma/","display_name":"CNRST","server_type":"institute_access","support_contact":["mailto:noc@cnrst.ma"]},{"base_url":"https://eduvpn-csc.funet.fi/","display_name":"CSC - IT Center for Science Ltd.","server_type":"institute_access","support_contact":["mailto:eduvpn@csc.fi"]},{"base_url":"https://eduvpn-01.worc.ac.uk/","display_name":{"en":"University of Worcester"},"server_type":"institute_access","support_contact":["tel:+441905857500","https://www2.worc.ac.uk/it/"]},{"base_url":"https://eduvpn.du.se/","display_name":{"en":"Dalarna University","sv":"H\u00f6gskolan Dalarna"},"server_type":"institute_access","support_contact":["mailto:support@du.se","tel:+4623778888"]},{"base_url":"https://demo.eduvpn.nl/","display_name":"Demo","server_type":"institute_access","support_contact":["mailto:eduvpn@surf.nl"]},{"base_url":"https://access.diak.fi/","display_name":"DIAK","server_type":"institute_access","support_contact":["mailto:tuki@diak.fi","tel:+358294696070"]},{"base_url":"https://egi.eduvpn.nl/","display_name":"EGI Foundation","keyword_list":"egi european grid initiative","server_type":"institute_access"},{"base_url":"https://eduvpn.ensma.fr/","display_name":"Ensma","server_type":"institute_access","support_contact":["mailto:dsi@ensma.fr"]},{"base_url":"https://eur.eduvpn.nl/","display_name":"Erasmus University Rotterdam","keyword_list":"erasmus universiteit rotterdam university eur","server_type":"institute_access"},{"base_url":"https://fontys.eduvpn.nl/","display_name":"Fontys","keyword_list":"fontys university of applied sciences hogescholen","server_type":"institute_access","support_contact":["https://fontys.nl/fontyshelpt/IT-ondersteuning.htm","tel:+31885077777","mailto:it-servicedesk@fontys.nl"]},{"base_url":"https://eduvpn.frederick.ac.cy/","display_name":"Frederick University","server_type":"institute_access","support_contact":["mailto:support@frederick.ac.cy","tel:+35722394444","https://support.frederick.ac.cy/"]},{"base_url":"https://vpn.tuiasi.ro/","display_name":{"en":"Gheorghe Asachi Technical University of Iasi","ro":"Gheorghe Asachi Technical University of Iasi"},"server_type":"institute_access","support_contact":["mailto:eduvpn_support@tuiasi.ro","tel:+40232701340","https://support.tuiasi.ro/"]},{"base_url":"https://leduvpn.kyabirwasc.org/","display_name":"Global Surgical Initiatives, Jinja","server_type":"institute_access","support_contact":["mailto:ivan.aine@kyabirwasc.org","tel:+256779609632"]},{"base_url":"https://prod-eduvpn01.geant.org/","display_name":"G\u00c9ANT","server_type":"institute_access","support_contact":["mailto:it@geant.org","tel:+441223371300"]},{"base_url":"https://eduvpn.heanet.ie/","display_name":"HEAnet","server_type":"institute_access","support_contact":["mailto:noc@heanet.ie","tel:+35316609040"]},{"base_url":"https://eduvpn.hs-osnabrueck.de/","display_name":"Hochschule Osnabr\u00fcck","server_type":"institute_access","support_contact":["https://www.hs-osnabrueck.de/servicedesk/","tel:+495419697100","mailto:servicedesk@hs-osnabrueck.de"]},{"base_url":"https://saxion.eduvpn.nl/","display_name":{"en":"Saxion University of Applied Sciences","nl":"Hogeschool Saxion"},"keyword_list":"saxion university of applied sciences hogeschool","server_type":"institute_access","support_contact":["tel:+31880193600","https://servicedesk.saxion.nl/"]},{"base_url":"https://edu-vpn.uni-erfurt.de/","display_name":{"de":"Universit\u00e4t Erfurt","en":"University of Erfurt"},"server_type":"institute_access","support_contact":["mailto:rz@uni-erfurt.de","tel:+493617375454","https://uni-erfurt.de/go/servicedesk"]},{"base_url":"https://eduvpn.taltech.ee/","display_name":{"ee":"Tallinna Tehnika\u00fclikool","en":"Taltech"},"keyword_list":"taltech tallinna tehnika\u00fclikool tallinn university of technology","server_type":"institute_access","support_contact":["mailto:helpdesk@taltech.ee","tel:+3726203333","https://it.taltech.ee/"]},{"base_url":"https://hiof.eduvpn.no/","display_name":{"nb":"H\u00f8gskolen i \u00d8stfold"},"server_type":"institute_access","support_contact":["mailto:kontakt@uninett.no"]},{"base_url":"https://vpn.ibgc.cnrs.fr/","display_name":"IBGC","server_type":"institute_access","support_contact":["https://www.ibgc.cnrs.fr/glpi/","mailto:informatique@ibgc.cnrs.fr"]},{"base_url":"https://eduvpn.idi.co.ug/","display_name":"IDI-Uganda","server_type":"institute_access","support_contact":["mailto:eduvpnsupport@idi.co.ug","tel:+256783670727"]},{"base_url":"https://eduvpn.ace.ac.ug/","display_name":"African Center of Excellence in Bioinformatics - Uganda","server_type":"institute_access","support_contact":["mailto:ace@idi.co.ug","https://ace.idi.co.ug/"]},{"base_url":"https://eduvpn.mengohospital.org/","display_name":"Mengo Hospital Nursing School","server_type":"institute_access"},{"base_url":"https://eduvpn.eshte.pt/","display_name":"Escola Superior de Hotelaria e Turismo do Estoril","keyword_list":"eshte","server_type":"institute_access","support_contact":["mailto:ajuda@eshte.pt"]},{"base_url":"https://eduvpn.ipb.pt/","display_name":"Instituto Polit\u00e9cnico de Bragan\u00e7a","server_type":"institute_access","support_contact":["mailto:ccom@ipb.pt","http://www.ipb.pt/si","tel:+351273303050"]},{"base_url":"https://vpn.jcrc.org.ug/","display_name":"JCRC - Uganda","server_type":"institute_access","support_contact":["mailto:aatukunda@jcrc.org.ug","tel:+256789711148"]},{"base_url":"https://eduvpn.karelia.fi/","display_name":"Karelia-ammattikorkeakoulu","server_type":"institute_access","support_contact":["mailto:helpdesk@karelia.fi"]},{"base_url":"https://controller.eduroam.ke/","display_name":"KENET","server_type":"institute_access","support_contact":["mailto:eduvpn@kenet.or.ke","tel:+254732150500"]},{"base_url":"https://khio.eduvpn.no/","display_name":{"nb":"Kunsth\u00f8gskolen"},"server_type":"institute_access","support_contact":["mailto:kontakt@uninett.no"]},{"base_url":"https://vpn.marwan.ma/","display_name":"MARWAN","server_type":"institute_access","support_contact":["tel:+212700062200","mailto:noc@marwan.ma"]},{"base_url":"https://esciencecenter.eduvpn.nl/","display_name":"Netherlands eScienceCenter","keyword_list":"netherlands escience center","server_type":"institute_access"},{"base_url":"https://nikhef.eduvpn.nl/","display_name":"Nikhef","keyword_list":"nikhef","server_type":"institute_access"},{"base_url":"https://nla.eduvpn.no/","display_name":{"nb":"NLA H\u00f8gskolen"},"server_type":"institute_access","support_contact":["mailto:kontakt@uninett.no"]},{"base_url":"https://phs.eduvpn.no/","display_name":{"en":"The Norwegian Police University College (PHS)","nb":"Politih\u00f8gskolen (PHS)"},"keyword_list":"phs oslo bod\u00f8 stavern kongsvinger","server_type":"institute_access","support_contact":["mailto:kontakt@uninett.no"]},{"base_url":"https://uis.eduvpn.no/","display_name":{"en":"University of Stavanger","nb":"Universitet i Stavanger"},"keyword_list":"uis","server_type":"institute_access","support_contact":["mailto:kontakt@uninett.no"]},{"base_url":"https://uia.eduvpn.no/","display_name":{"en":"University of Agder","nb":"Universitet i Agder"},"keyword_list":"uia campus kristiansand grimstad","server_type":"institute_access","support_contact":["mailto:kontakt@uninett.no"]},{"base_url":"https://eduvpn.hec.gov.pk/","display_name":"Pakistan Education & Research Network","server_type":"institute_access","support_contact":["mailto:eduvpn@pern.edu.pk"]},{"base_url":"https://eduvpn.perdanauniversity.edu.my/","display_name":"Perdana University","server_type":"institute_access","support_contact":["mailto:it-helpdesk@perdanauniversity.edu.my"]},{"base_url":"https://eduvpn.pionier.net.pl/","display_name":"PIONIER","server_type":"institute_access","support_contact":["mailto:contact@eduvpn.pionier.net.pl"]},{"base_url":"https://eduvpn.polsl.pl/","display_name":"Politechnika \u015al\u0105ska","server_type":"institute_access"},{"base_url":"https://ru.eduvpn.nl/","display_name":{"en-US":"Radboud University","nl-NL":"Radboud Universiteit"},"keyword_list":"university nijmegen ru universiteit","server_type":"institute_access"},{"base_url":"https://leduvpn.renu.ac.ug/","display_name":"RENU","server_type":"institute_access","support_contact":["tel:+256783979515","mailto:technical@renu.ac.ug"]},{"base_url":"https://stc.eduvpn.nl/","display_name":"STC Group","keyword_list":"stc opleiding scheepvaart edu","server_type":"institute_access"},{"base_url":"https://surfnet.eduvpn.nl/","display_name":"SURFnet","keyword_list":"surfnet bv surf konijn powered by","server_type":"institute_access"},{"base_url":"https://samas.eduvpn.no/","display_name":{"en":"S\u00e1mi University of Applied Sciences","nb":"S\u00e1mi allaskuvla"},"keyword_list":"samas sami suas","server_type":"institute_access","support_contact":["mailto:kontakt@uninett.no"]},{"base_url":"https://eduvpn.tuni.fi/","display_name":"Tampere Universities","server_type":"institute_access","support_contact":["mailto:it-helpdesk@tuni.fi","https://www.tuni.fi/it-palvelut"]},{"base_url":"https://tudelft.eduvpn.nl/","display_name":{"en":"Delft University of Technology","nl":"Technische Universiteit Delft"},"keyword_list":"technische universiteit delft tu university of technology tud tudelft","server_type":"institute_access","support_contact":["https://tudelft.topdesk.net/"]},{"base_url":"https://eduvpn.hochschule-trier.de/","display_name":{"de":"Hochschule Trier","en":"Trier University of Applied Sciences"},"server_type":"institute_access","support_contact":["https://www.hochschule-trier.de/rzht/it-support","tel:+496518103555","mailto:eduvpn@help.hochschule-trier.de"]},{"base_url":"https://trimbos.eduvpn.nl/","display_name":"Trimbos-instituut","keyword_list":"trimbos instituut","server_type":"institute_access"},{"base_url":"https://eduvpn.turkuamk.fi/","display_name":"Turku University of Applied Sciences","server_type":"institute_access","support_contact":["mailto:servicedesk@turkuamk.fi"]},{"base_url":"https://uninett.eduvpn.no/","display_name":"Uninett","server_type":"institute_access","support_contact":["mailto:kontakt@uninett.no"]},{"base_url":"https://norid.eduvpn.no/","display_name":"Norid","server_type":"institute_access","support_contact":["mailto:kontakt@uninett.no"]},{"base_url":"https://unit.eduvpn.no/","display_name":"Unit","server_type":"institute_access","support_contact":["mailto:kontakt@uninett.no"]},{"base_url":"https://cessda.eduvpn.no/","display_name":"CESSDA","server_type":"institute_access","support_contact":["mailto:kontakt@uninett.no"]},{"base_url":"https://eduvpn.uii.ac.id/","display_name":"Universitas Islam Indonesia","server_type":"institute_access","support_contact":["mailto:itsupport@uii.ac.id","https://bsi.uii.ac.id/","tel:+62274898444;ext=1414"]},{"base_url":"https://eduvpn.uminho.pt/","display_name":{"en-US":"University of Minho","pt-PT":"Universidade do Minho"},"server_type":"institute_access","support_contact":["mailto:servicedesk@scom.uminho.pt","tel:+351253601000"]},{"base_url":"https://eduvpn.unimes.fr/","display_name":{"en":"University of Nimes","fr":"Universit\u00e9 de Nimes"},"server_type":"institute_access","support_contact":["mailto:eduvpn@unimes.fr"]},{"base_url":"https://eduvpn.uni-osnabrueck.de/","display_name":{"de-DE":"Universit\u00e4t Osnabr\u00fcck","en-US":"University of Osnabr\u00fcck"},"server_type":"institute_access","support_contact":["https://www.rz.uni-osnabrueck.de/dienste/beratung/beratungsteam/index.html","tel:+495419693333","mailto:Beratung@rz.uni-osnabrueck.de"]},{"base_url":"https://ut.eduvpn.nl/","display_name":{"en-US":"University of Twente","nl-NL":"Universiteit Twente"},"keyword_list":"university of twente universiteit ut utwente","server_type":"institute_access"},{"base_url":"https://eduvpn.univ-reims.fr/","display_name":"Universit\u00e9 de Reims Champagne-Ardenne","server_type":"institute_access","support_contact":["https://helpdesk.univ-reims.fr/","mailto:support-eduvpn@univ-reims.fr"]},{"base_url":"https://eduvpn.univ-rennes1.fr/","display_name":"Universit\u00e9 de Rennes 1","server_type":"institute_access","support_contact":["https://assistance.univ-rennes1.fr/"]},{"base_url":"https://eduvpn.uphf.fr/","display_name":"Universit\u00e9 Polytechnique Hauts-de-France","server_type":"institute_access","support_contact":["mailto:vpn@uphf.fr","https://portail.uphf.fr/"]},{"base_url":"https://hku.eduvpn.nl/","display_name":{"en-US":"Utrecht School of the Arts","nl-NL":"Hogeschool voor de Kunsten Utrecht"},"keyword_list":"utrecht school of the arts hbo hku","server_type":"institute_access"},{"base_url":"https://eduvpn.vamk.fi/","display_name":"VAMK - University of Applied Sciences","server_type":"institute_access","support_contact":["mailto:helpdesk@vamk.fi"]},{"base_url":"https://vu.eduvpn.nl/","display_name":"Vrije Universiteit","keyword_list":"vu vrije universiteit amsterdam","server_type":"institute_access","support_contact":["mailto:servicedesk.it@vu.nl","tel:+31205980000"]},{"base_url":"https://zuyd.eduvpn.nl/","display_name":{"en":"Zuyd University","nl":"Zuyd Hogeschool"},"keyword_list":"zuyd hogeschool test university hbo","server_type":"institute_access","support_contact":["mailto:ict-servicedesk@zuyd.nl","tel:+31454006085"]},{"base_url":"https://eduvpn.lism.catholic.edu.au/","display_name":{"en":"Catholic Schools Lismore Diocese"},"server_type":"institute_access","support_contact":["https://helpdesk.lism.catholic.edu.au/","tel:+61266220422"]},{"base_url":"https://eduvpn.sifulan.my/","display_name":{"en":"SIFULAN Malaysian Access Federation"},"server_type":"institute_access","support_contact":["mailto:support@sifulan.my","https://www.sifulan.my/","tel:+60380814083"]},{"base_url":"https://eduvpn.ifw-dresden.de/","display_name":{"de":"IFW Dresden","en":"IFW Dresden"},"server_type":"institute_access","support_contact":["mailto:ticket@otrs.ifw-dresden.de","tel:+4935146590","https://otrs.ifw-dresden.de/otrs/index.pl"]},{"base_url":"https://eduvpn-staff.belnet.be/","display_name":{"en":"Belnet"},"server_type":"institute_access","support_contact":["mailto:services@belnet.be"]},{"base_url":"https://naturalis.eduvpn.nl/","display_name":"Naturalis Biodiversity Center","keyword_list":"naturalis biodiversity center","server_type":"institute_access","support_contact":["mailto:support@naturalis.nl"]},{"base_url":"https://prinsesmaximacentrum.eduvpn.nl/","display_name":"Prinses M\u00e1xima Centrum","keyword_list":"prinses m\u00e1xima maxima centrum kinderoncologie utrecht pmc","server_type":"institute_access","support_contact":["mailto:servicedesk@prinsesmaximacentrum.nl"]},{"base_url":"https://surf.eduvpn.nl/","display_name":"SURF BV","keyword_list":"surf powered by surfnet surfmarket surfsara surf-bureau co\u00f6peratie cooperatie surffoundation bv konijn","server_type":"institute_access","support_contact":["https://support.ia.surf.nl/"]},{"base_url":"https://ul.eduvpn.nl/","display_name":{"en":"Leiden University","nl":"Universiteit Leiden"},"keyword_list":"universiteit leiden university leidenuniv rul","server_type":"institute_access","support_contact":["mailto:helpdesk@issc.leidenuniv.nl","tel:+31715278888"]},{"base_url":"https://tum.eduvpn.lrz.de/","display_name":{"de-DE":"Technische Universit\u00e4t M\u00fcnchen via LRZ-VPN","en-EN":"Technical University of Munich via LRZ-VPN"},"keyword_list":"tum lrz tum.de","server_type":"institute_access","support_contact":["mailto:servicedesk@lrz.de","tel:+4989358318800","https://servicedesk.lrz.de/de/simplesubmit/52"]},{"base_url":"https://lmu.eduvpn.lrz.de/","display_name":{"de-DE":"Ludwig-Maximilians-Universit\u00e4t M\u00fcnchen via LRZ-VPN","en-EN":"University of Munich via LRZ-VPN"},"keyword_list":"lmu lrz lmu.de","server_type":"institute_access","support_contact":["mailto:servicedesk@lrz.de","tel:+4989358318800","https://servicedesk.lrz.de/de/simplesubmit/52"]},{"base_url":"https://hm.eduvpn.lrz.de/","display_name":{"de-DE":"Hochschule M\u00fcnchen via LRZ-VPN","en-EN":"University of Applied Sciences Munich via LRZ-VPN"},"keyword_list":"hm lrz hm.edu","server_type":"institute_access","support_contact":["mailto:servicedesk@lrz.de","tel:+4989358318800","https://servicedesk.lrz.de/de/simplesubmit/52"]},{"base_url":"https://int.eduvpn.lrz.de/","display_name":{"de-DE":"Leibniz Rechenzentrum intern via LRZ-VPN","en-EN":"Leibniz Supercomputing Centre internal via LRZ-VPN"},"keyword_list":"lrz badw lrz.de badw.de","server_type":"institute_access","support_contact":["mailto:servicedesk@lrz.de","tel:+4989358318800","https://servicedesk.lrz.de/de/simplesubmit/52"]},{"base_url":"https://eduvpn.univ-poitiers.fr/","display_name":{"en":"University of Poitiers","fr":"Universit\u00e9 de Poitiers"},"keyword_list":"vpn personnels","server_type":"institute_access","support_contact":["https://imedias.univ-poitiers.fr/"]},{"base_url":"https://vpn-ext.univ-poitiers.fr/","display_name":{"en":"University of Poitiers - External users","fr":"Universit\u00e9 de Poitiers - Intervenants externes"},"keyword_list":"vpn exterieurs","server_type":"institute_access","support_contact":["https://imedias.univ-poitiers.fr/"]},{"base_url":"https://eduvpn-etu.univ-poitiers.fr/","display_name":{"en":"University of Poitiers - Students","fr":"Universit\u00e9 de Poitiers - Etudiants"},"keyword_list":"vpn etudiants","server_type":"institute_access","support_contact":["https://imedias.univ-poitiers.fr/"]},{"base_url":"https://eduvpn-uhasselt.belnet.be/","display_name":{"en":"Hasselt University","nl":"Universiteit Hasselt"},"keyword_list":"uhasselt","server_type":"institute_access","support_contact":["mailto:servicedesk@uhasselt.be","https://servicedesk.uhasselt.be"]},{"base_url":"https://leduvpn1.heritage.co.ug/","display_name":"Heritage International School","keyword_list":"his","server_type":"institute_access","support_contact":["mailto:it@heritage.co.ug","tel:+256706434521"]},{"base_url":"https://hswt.eduvpn.lrz.de/","display_name":{"de-DE":"Hochschule Weihenstephan-Triesdorf via LRZ-VPN","en-EN":"Weihenstephan-Triesdorf University of Applied Sciences via LRZ-VPN"},"keyword_list":"hswt lrz hswt.de","server_type":"institute_access","support_contact":["mailto:servicedesk@lrz.de","tel:+4989358318800","https://servicedesk.lrz.de/de/simplesubmit/52"]},{"base_url":"https://rad.eduvpn.lrz.de/","display_name":{"de-DE":"M\u00fcnchner Wissenschaftsnetz via LRZ-VPN","en-EN":"Munich Scientific Network via LRZ-VPN"},"keyword_list":"mwn mwn.de radius lrz","server_type":"institute_access","support_contact":["mailto:servicedesk@lrz.de","tel:+4989358318800","https://servicedesk.lrz.de/de/simplesubmit/52"]},{"base_url":"https://eduvpn.umt.edu.my/","display_name":"Universiti Malaysia Terengganu","keyword_list":"umt","server_type":"institute_access","support_contact":["mailto:wifi.support@umt.edu.my","tel:+6096684489","https://ped.umt.edu.my/"]},{"base_url":"https://eduvpn.agrocampus-ouest.fr/","display_name":"Institut Agro - Agrocampus Ouest","server_type":"institute_access","support_contact":["https://assistance.agrocampus-ouest.fr/dsi","mailto:contact-dsi@agrocampus-ouest.fr"]},{"base_url":"https://eduvpn-hecondorcet.belnet.be/","display_name":"Haute Ecole Provinciale de Hainaut - Condorcet","keyword_list":"hecondorcet condorcet","server_type":"institute_access","support_contact":["mailto:support@hecondorcet.be"]},{"base_url":"https://eduvpn.uni-hildesheim.de/","display_name":{"de":"Universit\u00e4t Hildesheim","en":"University of Hildesheim"},"keyword_list":"hildesheim stiftung","server_type":"institute_access","support_contact":["mailto:rz-service@uni-hildesheim.de","tel:+49512188392888","https://www.uni-hildesheim.de/rz/kontakt"]},{"base_url":"https://eduvpn-1.mmu.edu.my/","display_name":"Multimedia University","keyword_list":"mmu","server_type":"institute_access","support_contact":["mailto:net@mmu.edu.my"]}]}
\ No newline at end of file diff --git a/test_data/real/server_list-1.json.pure.minisig b/test_data/real/server_list-1.json.pure.minisig deleted file mode 100644 index 33363a8..0000000 --- a/test_data/real/server_list-1.json.pure.minisig +++ /dev/null @@ -1,4 +0,0 @@ -untrusted comment: signature from minisign secret key -RWRtBSX1alxyGWh8DDGy+QqxCn+8eY3rBSbHkTUIQsQiX72l2u/Vk8mE3LSVglBlTPDOALe2iwt2v3UYr/lkOh/7e9XyZIj9Bwc= -trusted comment: timestamp:1636532257 file:server_list.json -OjouhJwceDYekSTnW9+UZcydaIWDhvQS1EyJkrJQNd1Z72zSTIGqK1fbCAZfKkFAmV3WSIa0fTxkh4E/dtgtBQ== diff --git a/test_data/dummy/secret.key b/test_data/secret.key index 6e4af37..6e4af37 100644 --- a/test_data/dummy/secret.key +++ b/test_data/secret.key diff --git a/test_data/dummy/server_list.json b/test_data/server_list.json index 67c4c8d..67c4c8d 100644 --- a/test_data/dummy/server_list.json +++ b/test_data/server_list.json diff --git a/test_data/dummy/server_list.json.blake2b b/test_data/server_list.json.blake2b Binary files differindex 5d2ca5a..5d2ca5a 100644 --- a/test_data/dummy/server_list.json.blake2b +++ b/test_data/server_list.json.blake2b diff --git a/test_data/dummy/server_list.json.forged_keyid.minisig b/test_data/server_list.json.forged_keyid.minisig index efa349d..efa349d 100644 --- a/test_data/dummy/server_list.json.forged_keyid.minisig +++ b/test_data/server_list.json.forged_keyid.minisig diff --git a/test_data/dummy/server_list.json.forged_pure.minisig b/test_data/server_list.json.forged_pure.minisig index a362504..a362504 100644 --- a/test_data/dummy/server_list.json.forged_pure.minisig +++ b/test_data/server_list.json.forged_pure.minisig diff --git a/test_data/dummy/server_list.json.large_time.minisig b/test_data/server_list.json.large_time.minisig index 79a2a52..79a2a52 100644 --- a/test_data/dummy/server_list.json.large_time.minisig +++ b/test_data/server_list.json.large_time.minisig diff --git a/test_data/dummy/server_list.json.minisig b/test_data/server_list.json.minisig index 143585b..143585b 100644 --- a/test_data/dummy/server_list.json.minisig +++ b/test_data/server_list.json.minisig diff --git a/test_data/dummy/server_list.json.pure.minisig b/test_data/server_list.json.pure.minisig index 57dccfc..57dccfc 100644 --- a/test_data/dummy/server_list.json.pure.minisig +++ b/test_data/server_list.json.pure.minisig diff --git a/test_data/dummy/server_list.json.tc_earliertime.minisig b/test_data/server_list.json.tc_earliertime.minisig index 03da710..03da710 100644 --- a/test_data/dummy/server_list.json.tc_earliertime.minisig +++ b/test_data/server_list.json.tc_earliertime.minisig diff --git a/test_data/dummy/server_list.json.tc_emptyfile.minisig b/test_data/server_list.json.tc_emptyfile.minisig index a7aa3ed..a7aa3ed 100644 --- a/test_data/dummy/server_list.json.tc_emptyfile.minisig +++ b/test_data/server_list.json.tc_emptyfile.minisig diff --git a/test_data/dummy/server_list.json.tc_emptytime.minisig b/test_data/server_list.json.tc_emptytime.minisig index d3ef01e..d3ef01e 100644 --- a/test_data/dummy/server_list.json.tc_emptytime.minisig +++ b/test_data/server_list.json.tc_emptytime.minisig diff --git a/test_data/dummy/server_list.json.tc_latertime.minisig b/test_data/server_list.json.tc_latertime.minisig index 8237123..8237123 100644 --- a/test_data/dummy/server_list.json.tc_latertime.minisig +++ b/test_data/server_list.json.tc_latertime.minisig diff --git a/test_data/dummy/server_list.json.tc_nofile.minisig b/test_data/server_list.json.tc_nofile.minisig index 3c1dcbe..3c1dcbe 100644 --- a/test_data/dummy/server_list.json.tc_nofile.minisig +++ b/test_data/server_list.json.tc_nofile.minisig diff --git a/test_data/dummy/server_list.json.tc_nohashed.minisig b/test_data/server_list.json.tc_nohashed.minisig index 1d140c1..1d140c1 100644 --- a/test_data/dummy/server_list.json.tc_nohashed.minisig +++ b/test_data/server_list.json.tc_nohashed.minisig diff --git a/test_data/dummy/server_list.json.tc_notime.minisig b/test_data/server_list.json.tc_notime.minisig index 39625c3..39625c3 100644 --- a/test_data/dummy/server_list.json.tc_notime.minisig +++ b/test_data/server_list.json.tc_notime.minisig diff --git a/test_data/dummy/server_list.json.tc_orglist.minisig b/test_data/server_list.json.tc_orglist.minisig index 7c2a3a8..7c2a3a8 100644 --- a/test_data/dummy/server_list.json.tc_orglist.minisig +++ b/test_data/server_list.json.tc_orglist.minisig diff --git a/test_data/dummy/server_list.json.tc_otherfile.minisig b/test_data/server_list.json.tc_otherfile.minisig index 58a29b2..58a29b2 100644 --- a/test_data/dummy/server_list.json.tc_otherfile.minisig +++ b/test_data/server_list.json.tc_otherfile.minisig diff --git a/test_data/dummy/server_list.json.tc_random.minisig b/test_data/server_list.json.tc_random.minisig index 7240980..7240980 100644 --- a/test_data/dummy/server_list.json.tc_random.minisig +++ b/test_data/server_list.json.tc_random.minisig diff --git a/test_data/dummy/server_list.json.wrong_key.minisig b/test_data/server_list.json.wrong_key.minisig index 5a83c0e..5a83c0e 100644 --- a/test_data/dummy/server_list.json.wrong_key.minisig +++ b/test_data/server_list.json.wrong_key.minisig diff --git a/test_data/dummy/wrong_public.key b/test_data/wrong_public.key index aa794d4..aa794d4 100644 --- a/test_data/dummy/wrong_public.key +++ b/test_data/wrong_public.key diff --git a/test_data/dummy/wrong_secret.key b/test_data/wrong_secret.key index 68e9092..68e9092 100644 --- a/test_data/dummy/wrong_secret.key +++ b/test_data/wrong_secret.key @@ -1,4 +1,4 @@ -package eduvpn_verify +package eduvpn_discovery import ( "fmt" @@ -6,9 +6,17 @@ import ( "os" ) +// getKeys returns keys taken from https://git.sr.ht/~eduvpn/disco.eduvpn.org#public-keys. +func getKeys() []string { + return []string{ + "RWRtBSX1alxyGX+Xn3LuZnWUT0w//B6EmTJvgaAxBMYzlQeI+jdrO6KF", // fkooman@tuxed.net, kolla@uninett.no + "RWQKqtqvd0R7rUDp0rWzbtYPA3towPWcLDCl7eY9pBMMI/ohCmrS0WiM", // RoSp + } +} + // Verify verifies the signature (.minisig file format) on signedJson. // -// expectedFileName must be set to the file type to be verified, either server_list.json or organization_list.json. +// expectedFileName must be set to the file type to be verified, either "server_list.json" or "organization_list.json". // minSign must be set to the minimum UNIX timestamp (without milliseconds) for the file version. // This value should not be smaller than the time on the previous document verified. // @@ -16,10 +24,7 @@ import ( // // Verify is a wrapper around verifyWithKeys where allowedPublicKeys is set to the list from https://git.sr.ht/~eduvpn/disco.eduvpn.org#public-keys. func Verify(signatureFileContent string, signedJson []byte, expectedFileName string, minSignTime uint64) (bool, error) { - keyStrs := []string{ - "RWRtBSX1alxyGX+Xn3LuZnWUT0w//B6EmTJvgaAxBMYzlQeI+jdrO6KF", // fkooman@tuxed.net, kolla@uninett.no - "RWQKqtqvd0R7rUDp0rWzbtYPA3towPWcLDCl7eY9pBMMI/ohCmrS0WiM", // RoSp - } + keyStrs := getKeys() if extraKey != "" { keyStrs = append(keyStrs, extraKey) _, err := fmt.Fprintf(os.Stderr, "INSECURE TEST MODE ENABLED WITH KEY %q\n", extraKey) @@ -37,22 +42,25 @@ func Verify(signatureFileContent string, signedJson []byte, expectedFileName str return valid, nil } -// Extra allowed key for testing +// extraKey is an extra allowed key for testing. var extraKey = "" // InsecureTestingSetExtraKey adds an extra allowed key for verification with Verify. -// ONLY USE FOR TESTING. Probably not thread-safe. Do not call in parallel to Verify. +// ONLY USE FOR TESTING. Applies to all threads. Probably not thread-safe. Do not call in parallel to Verify. +// +// keyString must be a Base64-encoded Minisign key, or empty to reset. func InsecureTestingSetExtraKey(keyString string) { extraKey = keyString } -type VerifyErrorCode int +// VerifyErrorCode Simplified error code for public interface. +type VerifyErrorCode int8 const ( - ErrUnknownExpectedFileName VerifyErrorCode = iota + 1 - ErrInvalidSignature - ErrInvalidSignatureUnknownKey - ErrTooOld + ErrUnknownExpectedFileName VerifyErrorCode = iota + 1 // Unknown expected file name specified. The signature has not been verified. + ErrInvalidSignature // Signature is invalid (for the expected file type). + ErrInvalidSignatureUnknownKey // Signature was created with an unknown key and has not been verified. + ErrTooOld // Signature timestamp smaller than specified minimum signing time (rollback). ) type VerifyError struct { @@ -71,9 +79,9 @@ func (err VerifyError) Unwrap() error { // // Verification is performed using a matching key in allowedPublicKeys. // The signature is checked to be a Blake2b-prehashed Ed25519 Minisign signature with a valid trusted comment. -// The file type that is verified is indicated by expectedFileName, which must be one of server_list.json/organization_list.json. +// The file type that is verified is indicated by expectedFileName, which must be one of "server_list.json"/"organization_list.json". // The trusted comment is checked to be of the form "timestamp:<timestamp>\tfile:<expectedFileName>", optionally suffixed by something, e.g. "\thashed". -// The signature is checked to have a timestamp with a value of at least minSignTime, which is a UNIX timestamp without milliseconds; +// The signature is checked to have a timestamp with a value of at least minSignTime, which is a UNIX timestamp without milliseconds. // // The return value will either be (true, nil) on success or (false, detailedVerifyError) on failure. func verifyWithKeys(signatureFileContent string, signedJson []byte, expectedFileName string, minSignTime uint64, allowedPublicKeys []string) (bool, error) { @@ -89,18 +97,21 @@ func verifyWithKeys(signatureFileContent string, signedJson []byte, expectedFile return false, detailedVerifyError{errInvalidSignatureFormat, "invalid signature format", err} } + // Check if signature is prehashed, see https://jedisct1.github.io/minisign/#signature-format if sig.SignatureAlgorithm != [2]byte{'E', 'D'} { return false, detailedVerifyError{errInvalidSignatureAlgorithm, "BLAKE2b-prehashed EdDSA signature required", nil} } + // Find allowed key used for signature for _, keyStr := range allowedPublicKeys { key, err := minisign.NewPublicKey(keyStr) if err != nil { + // Should only happen if Verify is wrong or extraKey is invalid return false, detailedVerifyError{errInvalidPublicKey, "internal error: could not create public key", err} } if sig.KeyId != key.KeyId { - continue + continue // Wrong key } valid, err := key.Verify(signedJson, sig) @@ -108,6 +119,7 @@ func verifyWithKeys(signatureFileContent string, signedJson []byte, expectedFile return false, detailedVerifyError{errInvalidSignature, "invalid signature", err} } + // Parse trusted comment var signTime uint64 var sigFileName string // sigFileName cannot have spaces @@ -127,10 +139,12 @@ func verifyWithKeys(signatureFileContent string, signedJson []byte, expectedFile return true, nil } - return false, detailedVerifyError{errWrongKey, "signature was created with unknown key", nil} + // No matching allowed key found + return false, detailedVerifyError{errWrongKey, "signature was created with an unknown key", nil} } -type detailedVerifyErrorCode int +// detailedVerifyErrorCode used for unit tests. +type detailedVerifyErrorCode int8 const ( errUnknownExpectedFileName detailedVerifyErrorCode = iota + 1 diff --git a/verify_test.go b/verify_test.go index 0689be1..769bfbc 100644 --- a/verify_test.go +++ b/verify_test.go @@ -1,4 +1,4 @@ -package eduvpn_verify +package eduvpn_discovery import ( "bufio" @@ -10,59 +10,18 @@ import ( "testing" ) -const ( - ok = -1 - errAny = -2 -) - -func compareResults(t *testing.T, ret bool, err error, expected int, call func() string) { - getCode := func(err error) int { - switch e := err.(type) { - case detailedVerifyError: - return int(e.Code) - case VerifyError: - return int(e.Code) - } - panic(nil) - } - - if (err == nil) != (expected == ok) || err != nil && expected != errAny && getCode(err) != expected { - var errMsg string - if err != nil { - errMsg = fmt.Sprintf("%v %v (cause %v)", getCode(err), err, errors.Unwrap(err)) - } else { - errMsg = "<ok>" - } - - var wantErrCode string - switch expected { - case ok: - wantErrCode = "<ok>" - case errAny: - wantErrCode = "<any>" - default: - wantErrCode = strconv.Itoa(expected) - } - - t.Errorf("%v\nerror = %v, wantErr %v", call(), errMsg, wantErrCode) - return - } - if ret != (expected == ok) { - t.Errorf("%v\n= %v, want %v", call(), ret, expected == ok) - } -} - func Test_verifyWithKeys(t *testing.T) { var err error var pk []string { - file, err := os.Open("test_data/dummy/public.key") + file, err := os.Open("test_data/public.key") if err != nil { panic(err) } defer file.Close() + // Get last line (key string) from file scanner := bufio.NewScanner(file) for i := 0; i < 2; i++ { if !scanner.Scan() { @@ -123,29 +82,24 @@ func Test_verifyWithKeys(t *testing.T) { {errInvalidPublicKey, "invalid allowed key", "server_list.json.minisig", "server_list.json", "server_list.json", 10, []string{"AAA"}}, } + // Cache file contents in map, mapping file names to contents files := map[string][]byte{} - for _, test := range tests { - signature, loaded := files[test.signatureFile] + loadFile := func(name string) { + content, loaded := files[name] if !loaded { - signature, err = ioutil.ReadFile("test_data/dummy/" + test.signatureFile) + content, err = ioutil.ReadFile("test_data/" + name) if err != nil { panic(err) } - files[test.signatureFile] = signature - } - - json, loaded := files[test.jsonFile] - if !loaded { - json, err = ioutil.ReadFile("test_data/dummy/" + test.jsonFile) - if err != nil { - panic(err) - } - files[test.jsonFile] = json + files[name] = content } } + for _, test := range tests { + loadFile(test.signatureFile) + loadFile(test.jsonFile) + } for _, tt := range tests { - tt := tt t.Run(tt.testName, func(t *testing.T) { t.Parallel() valid, err := verifyWithKeys(string(files[tt.signatureFile]), files[tt.jsonFile], @@ -158,52 +112,46 @@ func Test_verifyWithKeys(t *testing.T) { } } -func Test_Verify(t *testing.T) { - var err error - tests := []struct { - result VerifyErrorCode - testName string - signatureFile string - jsonFile string - expectedFileName string - minSignTime uint64 - }{ - //TODO tests with real valid *prehashed* signatures - {ErrInvalidSignature, "pure server_list", "server_list-1.json.pure.minisig", "server_list-1.json", "server_list.json", 1636532223}, - {ErrInvalidSignature, "pure organization_list", "organization_list-1.json.pure.minisig", "organization_list-1.json", "organization_list.json", 1636532223}, - {ErrInvalidSignatureUnknownKey, "wrong key", "../dummy/server_list.json.minisig", "../dummy/server_list.json", "server_list.json", 10}, +const ( + ok = -1 // Test should not give an error. + errAny = -2 // Test should give any error (specific error is an implementation detail). +) + +// compareResults compares returned ret, err from a verify function with expected error code expected. +// callStr is called to get the formatted parameters passed to the function. +func compareResults(t *testing.T, ret bool, err error, expected int, callStr func() string) { + getCode := func(err error) int { + switch e := err.(type) { + case detailedVerifyError: + return int(e.Code) + case VerifyError: + return int(e.Code) + } + panic(nil) } - files := map[string][]byte{} - for _, test := range tests { - signature, loaded := files[test.signatureFile] - if !loaded { - signature, err = ioutil.ReadFile("test_data/real/" + test.signatureFile) - if err != nil { - panic(err) - } - files[test.signatureFile] = signature + if (err == nil) != (expected == ok) || err != nil && expected != errAny && getCode(err) != expected { + var errMsg string + if err != nil { + errMsg = fmt.Sprintf("%v %v (cause %v)", getCode(err), err, errors.Unwrap(err)) + } else { + errMsg = "<ok>" } - json, loaded := files[test.jsonFile] - if !loaded { - json, err = ioutil.ReadFile("test_data/real/" + test.jsonFile) - if err != nil { - panic(err) - } - files[test.jsonFile] = json + var wantErrCode string + switch expected { + case ok: + wantErrCode = "<ok>" + case errAny: + wantErrCode = "<any>" + default: + wantErrCode = strconv.Itoa(expected) } - } - for _, tt := range tests { - tt := tt - t.Run(tt.testName, func(t *testing.T) { - t.Parallel() - valid, err := Verify(string(files[tt.signatureFile]), files[tt.jsonFile], tt.expectedFileName, tt.minSignTime) - compareResults(t, valid, err, int(tt.result), func() string { - return fmt.Sprintf("Verify(%q, %q, %q, %v)", - tt.signatureFile, tt.jsonFile, tt.expectedFileName, tt.minSignTime) - }) - }) + t.Errorf("%v\nerror = %v, wantErr %v", callStr(), errMsg, wantErrCode) + return + } + if ret != (expected == ok) { + t.Errorf("%v\n= %v, want %v", callStr(), ret, expected == ok) } } diff --git a/wrappers/csharp/Discovery.cs b/wrappers/csharp/Discovery.cs index 183d94f..da4a6ea 100644 --- a/wrappers/csharp/Discovery.cs +++ b/wrappers/csharp/Discovery.cs @@ -1,8 +1,10 @@ using System; +using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; +// Make InsecureTestingSetExtraKey visible to tests [assembly: InternalsVisibleTo("EduVpnCommonTests")] namespace EduVpnCommon @@ -11,12 +13,12 @@ namespace EduVpnCommon { /// <summary> /// Verifies the signature on the JSON server_list.json/organization_list.json file. - /// If the function returns the signature is valid for the given file type. + /// If the function returns, the signature is valid for the given file type. /// </summary> /// <param name="signatureFileContent">.minisig signature file contents.</param> /// <param name="signedJson">Signed .json file contents.</param> /// <param name="expectedFileName">The file type to be verified, one of <c>"server_list.json"</c> or <c>"organization_list.json"</c>.</param> - /// <param name="minSignTime">Minimum time for signature. Should be set to at least the time in a previously retrieved file.</param> + /// <param name="minSignTime">Minimum time for signature. Should be set to at least the time of the previous signature.</param> /// <exception cref="ArgumentException">If <c>expectedFileName</c> is not one of the allowed values.</exception> /// <exception cref="VerifyException">If signature verification fails.</exception> public static void Verify( @@ -35,11 +37,20 @@ namespace EduVpnCommon (ulong) minSignTime.ToUnixTimeSeconds()); } - if (result != VerifyReturnCode.Ok) + switch (result) { - if (result == VerifyReturnCode.ErrUnknownExpectedFileName) - throw new ArgumentException("unknown name", nameof(expectedFileName)); - throw new VerifyException((VerifyErrorCode) result); + case VerifyReturnCode.Ok: + return; + case VerifyReturnCode.ErrUnknownExpectedFileName: + throw new ArgumentException("unknown expected file name", nameof(expectedFileName)); + case VerifyReturnCode.ErrInvalidSignature: + throw new InvalidSignatureException(); + case VerifyReturnCode.ErrInvalidSignatureUnknownKey: + throw new InvalidSignatureUnknownKeyException(); + case VerifyReturnCode.ErrTooOld: + throw new SignatureTooOldException(); + default: + throw new UnknownVerifyException((sbyte) result); } } @@ -50,13 +61,17 @@ namespace EduVpnCommon InsecureTestingSetExtraKey(keyHandle.Slice); } - const string VerifyLibName = "eduvpn_verify"; + const string LibName = "eduvpn_common"; - [DllImport(VerifyLibName)] + [DllImport(LibName)] static extern VerifyReturnCode Verify(GoSlice signatureFileContent, GoSlice signedJson, GoSlice expectedFileName, ulong minSignTime); - [DllImport(VerifyLibName)] static extern void InsecureTestingSetExtraKey(GoSlice keyStr); + [DllImport(LibName)] static extern void InsecureTestingSetExtraKey(GoSlice keyStr); + /// <summary> + /// Safe auto-disposing Go slice handle. + /// Non-copying alternative to `Marshal.AllocHGlobal` etc. + /// </summary> class GoSliceHandle : IDisposable { GCHandle gcHandle_; @@ -68,6 +83,7 @@ namespace EduVpnCommon GoSliceHandle(Array array, int offset, int count) { + Debug.Assert(offset <= array.Length && /*prevent overflow:*/ count <= array.Length && offset <= array.Length - count); gcHandle_ = GCHandle.Alloc(array, GCHandleType.Pinned); var elemSize = Marshal.SizeOf(array.GetType().GetElementType()!); slice_ = new GoSlice(gcHandle_.AddrOfPinnedObject() + offset * elemSize, count * elemSize); @@ -76,12 +92,14 @@ namespace EduVpnCommon public static GoSliceHandle FromArray<T>(ArraySegment<T> segment) where T : struct => new GoSliceHandle(segment.Array!, segment.Offset, segment.Count); + /// <summary>From string as UTF-8.</summary> public static GoSliceHandle FromString(string str) => FromArray(new ArraySegment<byte>(Encoding.UTF8.GetBytes(str))); public void Dispose() => gcHandle_.Free(); } + // C-compatible structure readonly struct GoSlice { readonly IntPtr data_; @@ -98,38 +116,42 @@ namespace EduVpnCommon } } - public class VerifyException : Exception + /// <summary>Verification failed, do not trust the file.</summary> + public abstract class VerifyException : Exception { - public VerifyErrorCode Code { get; } - - internal VerifyException(VerifyErrorCode code) : base(GetMessage(code)) => Code = code; + protected VerifyException(string message) : base(message) { } + } - static string GetMessage(VerifyErrorCode code) => code switch - { - VerifyErrorCode.ErrInvalidSignature => "invalid signature", - VerifyErrorCode.ErrInvalidSignatureUnknownKey => "invalid signature (unknown key)", - VerifyErrorCode.ErrTooOld => "replay of previous signature (rollback)", - _ => $"unknown verify error ({code})" - }; + /// <summary>Signature is invalid (for the expected file type).</summary> + public sealed class InvalidSignatureException : VerifyException + { + public InvalidSignatureException() : base("invalid signature") { } } - public enum VerifyErrorCode + /// <summary>Signature was created with an unknown key and has not been verified.</summary> + public sealed class InvalidSignatureUnknownKeyException : VerifyException { - /// <summary>Signature is invalid (for the expected file type).</summary> - ErrInvalidSignature = VerifyReturnCode.ErrUnknownExpectedFileName + 1, + public InvalidSignatureUnknownKeyException() : base("invalid signature (unknown key)") { } + } - /// <summary>Signature was created with an unknown key and has not been verified.</summary> - ErrInvalidSignatureUnknownKey, + /// <summary>Signature timestamp smaller than specified minimum signing time (rollback).</summary> + public sealed class SignatureTooOldException : VerifyException + { + public SignatureTooOldException() : base("replay of previous signature (rollback)") { } + } - /// <summary>Signature has a timestamp lower than the specified minimum signing time.</summary> - ErrTooOld + /// <summary>Other unknown error.</summary> + public sealed class UnknownVerifyException : VerifyException + { + public UnknownVerifyException(sbyte code) : base($"unknown verify error ({code})") => Debug.Assert(code != 0); } - enum VerifyReturnCode + enum VerifyReturnCode : sbyte { Ok, - ErrUnknownExpectedFileName - - //... + ErrUnknownExpectedFileName, + ErrInvalidSignature, + ErrInvalidSignatureUnknownKey, + ErrTooOld } -}
\ No newline at end of file +} diff --git a/wrappers/csharp/EduVpnCommon.csproj b/wrappers/csharp/EduVpnCommon.csproj index 4643da2..587601c 100644 --- a/wrappers/csharp/EduVpnCommon.csproj +++ b/wrappers/csharp/EduVpnCommon.csproj @@ -1,4 +1,4 @@ -<Project Sdk="Microsoft.NET.Sdk"> +<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>netstandard2.0</TargetFramework> @@ -13,58 +13,59 @@ <ItemGroup> <Compile Remove="EduVpnCommonTests/**" /> - </ItemGroup> - - <ItemGroup> <EmbeddedResource Remove="EduVpnCommonTests/**" /> + <None Remove="EduVpnCommonTests/**" /> </ItemGroup> + <!-- Include EXPORTS_LIB_PATH, LIB_NAME definitions --> + <ImportGroup Label="PropertySheets"> + <Import Project="EduVpnCommon.props" /> + </ImportGroup> + <Target Name="Build library for current OS" BeforeTargets="PrepareForBuild" - Condition="!(Exists('../../exports/windows/amd64/eduvpn_verify.dll') - Or Exists('../../exports/windows/386/eduvpn_verify.dll') - Or Exists('../../exports/windows/arm/eduvpn_verify.dll') - Or Exists('../../exports/windows/arm64/eduvpn_verify.dll') - Or Exists('../../exports/linux/amd64/libeduvpn_verify.so') - Or Exists('../../exports/linux/arm/libeduvpn_verify.so') - Or Exists('../../exports/linux/arm64/libeduvpn_verify.so'))"> - <Message Text="Shared eduvpn_verify library not found, you should build that one first" Importance="high" /> + Condition="!(Exists('$(EXPORTS_LIB_PATH)/windows/amd64/$(LIB_NAME).dll') + Or Exists('$(EXPORTS_LIB_PATH)/windows/386/$(LIB_NAME).dll') + Or Exists('$(EXPORTS_LIB_PATH)/windows/arm/$(LIB_NAME).dll') + Or Exists('$(EXPORTS_LIB_PATH)/windows/arm64/$(LIB_NAME).dll') + Or Exists('$(EXPORTS_LIB_PATH)/linux/amd64/lib$(LIB_NAME).so') + Or Exists('$(EXPORTS_LIB_PATH)/linux/arm/lib$(LIB_NAME).so') + Or Exists('$(EXPORTS_LIB_PATH)/linux/arm64/lib$(LIB_NAME).so'))"> + <Message Text="!! Shared $(LIB_NAME) library not found, you should build that one first" Importance="high" /> </Target> <ItemGroup> - <None Remove="EduVpnCommonTests/**" /> - <!-- See https://docs.microsoft.com/en-us/nuget/create-packages/supporting-multiple-target-frameworks#architecture-specific-folders and https://docs.microsoft.com/en-us/dotnet/core/rid-catalog --> - <None Condition="Exists('../../exports/windows/amd64/eduvpn_verify.dll')" - Include="../../exports/windows/amd64/eduvpn_verify.dll" Pack="true" PackagePath="runtimes/win-x64/native/"> + <None Condition="Exists('$(EXPORTS_LIB_PATH)/windows/amd64/$(LIB_NAME).dll')" + Include="$(EXPORTS_LIB_PATH)/windows/amd64/$(LIB_NAME).dll" Pack="true" PackagePath="runtimes/win-x64/native/"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> - <None Condition="Exists('../../exports/windows/386/eduvpn_verify.dll')" - Include="../../exports/windows/386/eduvpn_verify.dll" Pack="true" PackagePath="runtimes/win-x86/native/"> + <None Condition="Exists('$(EXPORTS_LIB_PATH)/windows/386/$(LIB_NAME).dll')" + Include="$(EXPORTS_LIB_PATH)/windows/386/$(LIB_NAME).dll" Pack="true" PackagePath="runtimes/win-x86/native/"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> - <None Condition="Exists('../../exports/windows/arm/eduvpn_verify.dll')" - Include="../../exports/windows/arm/eduvpn_verify.dll" Pack="true" PackagePath="runtimes/win-arm/native/"> + <None Condition="Exists('$(EXPORTS_LIB_PATH)/windows/arm/$(LIB_NAME).dll')" + Include="$(EXPORTS_LIB_PATH)/windows/arm/$(LIB_NAME).dll" Pack="true" PackagePath="runtimes/win-arm/native/"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> - <None Condition="Exists('../../exports/windows/arm64/eduvpn_verify.dll')" - Include="../../exports/windows/arm64/eduvpn_verify.dll" Pack="true" PackagePath="runtimes/win-arm64/native/"> + <None Condition="Exists('$(EXPORTS_LIB_PATH)/windows/arm64/$(LIB_NAME).dll')" + Include="$(EXPORTS_LIB_PATH)/windows/arm64/$(LIB_NAME).dll" Pack="true" PackagePath="runtimes/win-arm64/native/"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> - <None Condition="Exists('../../exports/linux/amd64/libeduvpn_verify.so')" - Include="../../exports/linux/amd64/libeduvpn_verify.so" Pack="true" PackagePath="runtimes/linux-x64/native/"> + <None Condition="Exists('$(EXPORTS_LIB_PATH)/linux/amd64/lib$(LIB_NAME).so')" + Include="$(EXPORTS_LIB_PATH)/linux/amd64/lib$(LIB_NAME).so" Pack="true" PackagePath="runtimes/linux-x64/native/"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> - <None Condition="Exists('../../exports/linux/arm/libeduvpn_verify.so')" - Include="../../exports/linux/arm/libeduvpn_verify.so" Pack="true" PackagePath="runtimes/linux-arm/native/"> + <None Condition="Exists('$(EXPORTS_LIB_PATH)/linux/arm/lib$(LIB_NAME).so')" + Include="$(EXPORTS_LIB_PATH)/linux/arm/lib$(LIB_NAME).so" Pack="true" PackagePath="runtimes/linux-arm/native/"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> - <None Condition="Exists('../../exports/linux/arm64/libeduvpn_verify.so')" - Include="../../exports/linux/arm64/libeduvpn_verify.so" Pack="true" PackagePath="runtimes/linux-arm64/native/"> + <None Condition="Exists('$(EXPORTS_LIB_PATH)/linux/arm64/lib$(LIB_NAME).so')" + Include="$(EXPORTS_LIB_PATH)/linux/arm64/lib$(LIB_NAME).so" Pack="true" PackagePath="runtimes/linux-arm64/native/"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> </ItemGroup> diff --git a/wrappers/csharp/EduVpnCommon.props b/wrappers/csharp/EduVpnCommon.props new file mode 100644 index 0000000..97c2289 --- /dev/null +++ b/wrappers/csharp/EduVpnCommon.props @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <EXPORTS_LIB_PATH Condition="'$(EXPORTS_LIB_PATH)' == ''">$(SolutionDir)../../exports/lib</EXPORTS_LIB_PATH> + <LIB_NAME Condition="'$(LIB_NAME)' == ''">eduvpn_common</LIB_NAME> + </PropertyGroup> +</Project> diff --git a/wrappers/csharp/EduVpnCommonTests/VerifyTests.cs b/wrappers/csharp/EduVpnCommonTests/VerifyTests.cs index 41faf87..2d4a565 100644 --- a/wrappers/csharp/EduVpnCommonTests/VerifyTests.cs +++ b/wrappers/csharp/EduVpnCommonTests/VerifyTests.cs @@ -14,11 +14,11 @@ namespace EduVpnCommonTests [OneTimeSetUp] public void OneTimeSetUp() => - Discovery.InsecureTestingSetExtraKey(File.ReadLines($"{testDataDir_}/dummy/public.key").Last()); + Discovery.InsecureTestingSetExtraKey(File.ReadLines($"{testDataDir_}/public.key").Last()); [Test] - [TestCase("dummy/server_list.json.minisig", "dummy/server_list.json", "server_list.json")] - [TestCase("dummy/organization_list.json.minisig", "dummy/organization_list.json", "organization_list.json")] + [TestCase("server_list.json.minisig", "server_list.json", "server_list.json")] + [TestCase("organization_list.json.minisig", "organization_list.json", "organization_list.json")] public void TestValid(string sigFile, string jsonFile, string expectedFileName) => Discovery.Verify( File.ReadAllBytes($"{testDataDir_}/{sigFile}"), @@ -27,7 +27,7 @@ namespace EduVpnCommonTests DateTimeOffset.UnixEpoch); [Test] - [TestCase("dummy/server_list.json.minisig", "dummy/server_list.json", "server_list.json")] + [TestCase("server_list.json.minisig", "server_list.json", "server_list.json")] public void TestValidSegment(string sigFile, string jsonFile, string expectedFileName) { var bytes = new byte[] { 1, 2, 3 }.Concat(File.ReadAllBytes($"{testDataDir_}/{jsonFile}")) @@ -40,10 +40,9 @@ namespace EduVpnCommonTests } [Test] - [TestCase("dummy/random.txt", "dummy/server_list.json", "server_list.json")] + [TestCase("random.txt", "server_list.json", "server_list.json")] public void TestInvalidSignature(string sigFile, string jsonFile, string expectedFileName) => - Assert.Throws(Is.TypeOf<VerifyException>() - .And.Property(nameof(VerifyException.Code)).EqualTo(VerifyErrorCode.ErrInvalidSignature), + Assert.Throws<InvalidSignatureException>( () => Discovery.Verify( File.ReadAllBytes($"{testDataDir_}/{sigFile}"), File.ReadAllBytes($"{testDataDir_}/{jsonFile}"), @@ -51,10 +50,9 @@ namespace EduVpnCommonTests DateTimeOffset.UnixEpoch)); [Test] - [TestCase("dummy/server_list.json.wrong_key.minisig", "dummy/server_list.json", "server_list.json")] + [TestCase("server_list.json.wrong_key.minisig", "server_list.json", "server_list.json")] public void TestWrongKey(string sigFile, string jsonFile, string expectedFileName) => - Assert.Throws(Is.TypeOf<VerifyException>() - .And.Property(nameof(VerifyException.Code)).EqualTo(VerifyErrorCode.ErrInvalidSignatureUnknownKey), + Assert.Throws<InvalidSignatureUnknownKeyException>( () => Discovery.Verify( File.ReadAllBytes($"{testDataDir_}/{sigFile}"), File.ReadAllBytes($"{testDataDir_}/{jsonFile}"), @@ -62,10 +60,9 @@ namespace EduVpnCommonTests DateTimeOffset.UnixEpoch)); [Test] - [TestCase("dummy/server_list.json.minisig", "dummy/server_list.json", "server_list.json")] + [TestCase("server_list.json.minisig", "server_list.json", "server_list.json")] public void TestOldSignature(string sigFile, string jsonFile, string expectedFileName) => - Assert.Throws(Is.TypeOf<VerifyException>() - .And.Property(nameof(VerifyException.Code)).EqualTo(VerifyErrorCode.ErrTooOld), + Assert.Throws<SignatureTooOldException>( () => Discovery.Verify( File.ReadAllBytes($"{testDataDir_}/{sigFile}"), File.ReadAllBytes($"{testDataDir_}/{jsonFile}"), @@ -73,7 +70,7 @@ namespace EduVpnCommonTests DateTimeOffset.MaxValue)); [Test] - [TestCase("dummy/other_list.json.minisig", "dummy/other_list.json", "other_list.json")] + [TestCase("other_list.json.minisig", "other_list.json", "other_list.json")] public void TestUnknownExpectedFile(string sigFile, string jsonFile, string expectedFileName) => Assert.Throws<ArgumentException>( () => Discovery.Verify( @@ -82,4 +79,4 @@ namespace EduVpnCommonTests expectedFileName, DateTimeOffset.UnixEpoch)); } -}
\ No newline at end of file +} diff --git a/wrappers/csharp/Makefile b/wrappers/csharp/Makefile index 1761edc..29f9682 100644 --- a/wrappers/csharp/Makefile +++ b/wrappers/csharp/Makefile @@ -1,5 +1,9 @@ .PHONY: build pack test clean +EXPORTS_PATH ?= ../../exports +# Export, see EduVpnCommon.props +export EXPORTS_LIB_PATH ?= $(EXPORTS_PATH)/lib + build: dotnet publish EduVpnCommon.csproj --configuration Release @@ -7,7 +11,11 @@ pack: dotnet pack EduVpnCommon.csproj --configuration Release test: - $(MAKE) -C ../../exports +ifneq ($(EXPORTS_PATH),) +ifneq ($(wildcard $(EXPORTS_PATH)/Makefile),) + $(MAKE) -C "$(EXPORTS_PATH)" +endif +endif dotnet test clean: diff --git a/wrappers/csharp/README.md b/wrappers/csharp/README.md index d4d1d97..32d2330 100644 --- a/wrappers/csharp/README.md +++ b/wrappers/csharp/README.md @@ -3,33 +3,38 @@ ## Requirements You will need to install the [.NET SDK](https://dotnet.microsoft.com/download), which includes the `dotnet` tool. The -wrapper targets .NET Standard 2.0, so which means that at least .NET Core 2.0 is required (.NET 5+ is also fine). For -the tests, .NET 5 or newer is required. +wrapper targets .NET Standard 2.0, which means that at least .NET Core 2.0 is required (.NET 5+ is also fine). For the +tests, .NET 5 is required. ## Build & test First build the shared Go library. Next: -Build `EduVpnCommon`: +Build `EduVpnCommon` (Release): ```shell make ``` -Build as nupkg, including eduvpn_verify library: +Build as nupkg, including shared Go library for all platforms built in `exports/lib/`: ```shell make pack ``` +If you do not build this as part of the full repository, specify `EXPORTS_PATH="" EXPORTS_LIB_PATH="path/to/lib-folder"` +when calling make. + The wrapper targets .NET Standard 2.0, which means that it can be referenced by projects using either .NET Framework 4.6.1+, .NET Core 2.0+, or .NET 5+. Currently, directly referencing the project may not work (with `System.BadImageFormatException`) if you have multiple -dynamic libraries compiled in the `exports` folder. If you instead add the `.nupkg`, e.g. with one of the +dynamic libraries compiled in the `exports/lib/` folder. If you instead add the `.nupkg`, e.g. with one of the methods [here](https://stackoverflow.com/q/43400069) or [here](https://stackoverflow.com/q/10240029), it automatically copies the correct library. +This also means that tests may fail if you have multiple dynamic libraries compiled! + Test: ```shell diff --git a/wrappers/java/Makefile b/wrappers/java/Makefile index 4b7b602..a63aef7 100644 --- a/wrappers/java/Makefile +++ b/wrappers/java/Makefile @@ -1,14 +1,21 @@ .PHONY: build pack test clean +EXPORTS_PATH ?= ../../exports +EXPORTS_LIB_PATH ?= $(EXPORTS_PATH)/lib + build: - mvn --no-transfer-progress compile + mvn --no-transfer-progress compile -DEXPORTS_LIB_PATH="$(EXPORTS_LIB_PATH)" pack: - mvn --no-transfer-progress package + mvn --no-transfer-progress package -DEXPORTS_LIB_PATH="$(EXPORTS_LIB_PATH)" test: - $(MAKE) -C ../../exports - mvn --no-transfer-progress test +ifneq ($(EXPORTS_PATH),) +ifneq ($(wildcard $(EXPORTS_PATH)/Makefile),) + $(MAKE) -C "$(EXPORTS_PATH)" +endif +endif + mvn --no-transfer-progress test -DEXPORTS_LIB_PATH="$(EXPORTS_LIB_PATH)" clean: rm -rf target/ diff --git a/wrappers/java/README.md b/wrappers/java/README.md index 87cdd49..b72d90e 100644 --- a/wrappers/java/README.md +++ b/wrappers/java/README.md @@ -16,7 +16,7 @@ Build `EduVpnCommon`: make ``` -Build as JAR, including eduvpn_verify library: +Build as JAR, including shared Go library: ```shell make pack diff --git a/wrappers/java/pom.xml b/wrappers/java/pom.xml index bd9f721..520bd34 100644 --- a/wrappers/java/pom.xml +++ b/wrappers/java/pom.xml @@ -10,9 +10,11 @@ <name>eduVPN common library</name> <properties> - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <maven.compiler.source>1.8</maven.compiler.source> - <maven.compiler.target>1.8</maven.compiler.target> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <maven.compiler.source>1.8</maven.compiler.source> + <maven.compiler.target>1.8</maven.compiler.target> + + <EXPORTS_LIB_PATH>../../exports/lib</EXPORTS_LIB_PATH> </properties> <dependencies> @@ -40,21 +42,21 @@ <!-- See com.sun.jna.Platform#getNativeLibraryResourcePrefix --> <resource> - <directory>../../exports/linux/amd64</directory> + <directory>${EXPORTS_LIB_PATH}/linux/amd64</directory> <includes> <include>*.so</include> </includes> <targetPath>linux-x86-64</targetPath> </resource> <resource> - <directory>../../exports/linux/arm</directory> + <directory>${EXPORTS_LIB_PATH}/linux/arm</directory> <includes> <include>*.so</include> </includes> <targetPath>linux-arm</targetPath> </resource> <resource> - <directory>../../exports/linux/arm64</directory> + <directory>${EXPORTS_LIB_PATH}/linux/arm64</directory> <includes> <include>*.so</include> </includes> @@ -62,36 +64,38 @@ </resource> <resource> - <directory>../../exports/windows/amd64</directory> + <directory>${EXPORTS_LIB_PATH}/windows/amd64</directory> <includes> <include>*.dll</include> </includes> <targetPath>win32-x86-64</targetPath> </resource> <resource> - <directory>../../exports/windows/386</directory> + <directory>${EXPORTS_LIB_PATH}/windows/386</directory> <includes> <include>*.dll</include> </includes> <targetPath>win32-x86</targetPath> </resource> <resource> - <directory>../../exports/windows/arm</directory> + <directory>${EXPORTS_LIB_PATH}/windows/arm</directory> <includes> <include>*.dll</include> </includes> <targetPath>win32-arm</targetPath> </resource> <resource> - <directory>../../exports/windows/arm64</directory> + <directory>${EXPORTS_LIB_PATH}/windows/arm64</directory> <includes> <include>*.dll</include> </includes> <targetPath>win32-arm64</targetPath> </resource> </resources> + <plugins> <plugin> + <!-- Test adapter --> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.1</version> diff --git a/wrappers/java/src/main/java/nl/eduvpn/common/Discovery.java b/wrappers/java/src/main/java/nl/eduvpn/common/Discovery.java index 40d5300..69308c8 100644 --- a/wrappers/java/src/main/java/nl/eduvpn/common/Discovery.java +++ b/wrappers/java/src/main/java/nl/eduvpn/common/Discovery.java @@ -6,38 +6,48 @@ import java.nio.charset.StandardCharsets; import java.time.Instant; public final class Discovery { - private static final NativeApi discovery = Native.load("eduvpn_verify", NativeApi.class); + private static final String LIB_NAME = "eduvpn_common"; + private static final NativeApi discovery = Native.load(LIB_NAME, NativeApi.class); /** * Verifies the signature on the JSON server_list.json/organization_list.json file. - * If the function returns the signature is valid for the given file type. + * If the function returns, the signature is valid for the given file type. * * @param signature .minisig signature file contents. * @param signedJson Signed .json file contents. * @param expectedFileName The file type to be verified, one of {@code "server_list.json"} or {@code "organization_list.json"}. - * @param minSignTime Minimum time for signature. Should be set to at least the time in a previously retrieved file. + * @param minSignTime Minimum time for signature. Should be set to at least the time of the previous signature. * @throws IllegalArgumentException If {@code expectedFileName} is not one of the allowed values or one of the parameters is empty. * @throws VerifyException If signature verification fails. */ public static void verify(byte[] signature, byte[] signedJson, String expectedFileName, Instant minSignTime) throws VerifyException { - long err = discovery.Verify(NativeApi.GoSlice.make(signature), NativeApi.GoSlice.make(signedJson), - NativeApi.GoSlice.make(expectedFileName.getBytes(StandardCharsets.UTF_8)), - minSignTime.getEpochSecond()); - if (err != 0) { - if (err == 1) throw new IllegalArgumentException("Unknown excpectedFileName"); - throw new VerifyException(err); + byte err = discovery.Verify(NativeApi.GoSlice.fromArray(signature), NativeApi.GoSlice.fromArray(signedJson), + NativeApi.GoSlice.fromString(expectedFileName), minSignTime.getEpochSecond()); + + switch (err) { + case 0: + return; + case 1: + throw new IllegalArgumentException("unknown expected file name"); + case 2: + throw new InvalidSignatureException(); + case 3: + throw new InvalidSignatureUnknownKeyException(); + case 4: + throw new SignatureTooOldException(); + default: + throw new UnknownVerifyException(err); } } - /** - * Use for testing only, see Go documentation. - */ - // package-private + /** Use for testing only, see Go documentation. */ + /*package-private*/ static void insecureTestingSetExtraKey(String keyString) { - discovery.InsecureTestingSetExtraKey(NativeApi.GoSlice.make(keyString.getBytes(StandardCharsets.UTF_8))); + discovery.InsecureTestingSetExtraKey(NativeApi.GoSlice.fromArray(keyString.getBytes(StandardCharsets.UTF_8))); } private interface NativeApi extends Library { + // C-compatible structure @Structure.FieldOrder({"data", "len", "cap"}) class GoSlice extends Structure implements Structure.ByValue { public Pointer data; @@ -49,14 +59,19 @@ public final class Discovery { this.cap = cap; } - public static GoSlice make(byte[] bytes) { + public static GoSlice fromArray(byte[] bytes) { Memory memory = new Memory(bytes.length); memory.write(0, bytes, 0, bytes.length); return new GoSlice(memory, bytes.length, bytes.length); } + + /** From string as UTF-8. */ + public static GoSlice fromString(String str) { + return fromArray(str.getBytes(StandardCharsets.UTF_8)); + } } - long Verify(GoSlice signatureFileContent, GoSlice signedJson, GoSlice expectedFileName, long minSignTime); + byte Verify(GoSlice signatureFileContent, GoSlice signedJson, GoSlice expectedFileName, long minSignTime); void InsecureTestingSetExtraKey(GoSlice keyString); } diff --git a/wrappers/java/src/main/java/nl/eduvpn/common/InvalidSignatureException.java b/wrappers/java/src/main/java/nl/eduvpn/common/InvalidSignatureException.java new file mode 100644 index 0000000..e531206 --- /dev/null +++ b/wrappers/java/src/main/java/nl/eduvpn/common/InvalidSignatureException.java @@ -0,0 +1,8 @@ +package nl.eduvpn.common; + +/** Signature is invalid (for the expected file type). */ +public final class InvalidSignatureException extends VerifyException { + public InvalidSignatureException() { + super("invalid signature"); + } +} diff --git a/wrappers/java/src/main/java/nl/eduvpn/common/InvalidSignatureUnknownKeyException.java b/wrappers/java/src/main/java/nl/eduvpn/common/InvalidSignatureUnknownKeyException.java new file mode 100644 index 0000000..8eaf661 --- /dev/null +++ b/wrappers/java/src/main/java/nl/eduvpn/common/InvalidSignatureUnknownKeyException.java @@ -0,0 +1,8 @@ +package nl.eduvpn.common; + +/** Signature was created with an unknown key and has not been verified. */ +public final class InvalidSignatureUnknownKeyException extends VerifyException { + public InvalidSignatureUnknownKeyException() { + super("invalid signature (unknown key)"); + } +} diff --git a/wrappers/java/src/main/java/nl/eduvpn/common/SignatureTooOldException.java b/wrappers/java/src/main/java/nl/eduvpn/common/SignatureTooOldException.java new file mode 100644 index 0000000..c40c718 --- /dev/null +++ b/wrappers/java/src/main/java/nl/eduvpn/common/SignatureTooOldException.java @@ -0,0 +1,8 @@ +package nl.eduvpn.common; + +/** Signature timestamp smaller than specified minimum signing time (rollback). */ +public final class SignatureTooOldException extends VerifyException { + public SignatureTooOldException() { + super("replay of previous signature (rollback)"); + } +} diff --git a/wrappers/java/src/main/java/nl/eduvpn/common/UnknownVerifyException.java b/wrappers/java/src/main/java/nl/eduvpn/common/UnknownVerifyException.java new file mode 100644 index 0000000..fa76a44 --- /dev/null +++ b/wrappers/java/src/main/java/nl/eduvpn/common/UnknownVerifyException.java @@ -0,0 +1,9 @@ +package nl.eduvpn.common; + +/** Other unknown error. */ +public final class UnknownVerifyException extends VerifyException { + public UnknownVerifyException(byte code) { + super(String.format("unknown verify error (%d)", code)); + assert code != 0; + } +} diff --git a/wrappers/java/src/main/java/nl/eduvpn/common/VerifyException.java b/wrappers/java/src/main/java/nl/eduvpn/common/VerifyException.java index 83dffb1..71ea290 100644 --- a/wrappers/java/src/main/java/nl/eduvpn/common/VerifyException.java +++ b/wrappers/java/src/main/java/nl/eduvpn/common/VerifyException.java @@ -1,9 +1,8 @@ package nl.eduvpn.common; -public class VerifyException extends Exception { - public final long code; //TODO not use plain long - - public VerifyException(long code) { - this.code = code; +/** Verification failed, do not trust the file. */ +public abstract class VerifyException extends Exception { + protected VerifyException(String message) { + super(message); } -}
\ No newline at end of file +} diff --git a/wrappers/java/src/test/java/nl/eduvpn/common/VerifyTests.java b/wrappers/java/src/test/java/nl/eduvpn/common/VerifyTests.java index b4767a5..a82c019 100644 --- a/wrappers/java/src/test/java/nl/eduvpn/common/VerifyTests.java +++ b/wrappers/java/src/test/java/nl/eduvpn/common/VerifyTests.java @@ -1,6 +1,5 @@ package nl.eduvpn.common; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -18,15 +17,15 @@ class VerifyTests { @SuppressWarnings("OptionalGetWithoutIsPresent") @BeforeAll static void oneTimeSetup() throws IOException { - Discovery.insecureTestingSetExtraKey(Files.lines(testDataDir.resolve("dummy/public.key")).reduce((a, b) -> b).get()); + Discovery.insecureTestingSetExtraKey(Files.lines(testDataDir.resolve("public.key")).reduce((a, b) -> b).get()); } @Test void testValid() { assertDoesNotThrow(() -> Discovery.verify( - Files.readAllBytes(testDataDir.resolve("dummy/server_list.json.minisig")), - Files.readAllBytes(testDataDir.resolve("dummy/server_list.json")), + Files.readAllBytes(testDataDir.resolve("server_list.json.minisig")), + Files.readAllBytes(testDataDir.resolve("server_list.json")), "server_list.json", Instant.EPOCH )); @@ -34,45 +33,45 @@ class VerifyTests { @Test void testInvalidSignature() { - Assertions.assertEquals(2, assertThrows(VerifyException.class, () -> + assertThrows(InvalidSignatureException.class, () -> Discovery.verify( - Files.readAllBytes(testDataDir.resolve("dummy/random.txt")), - Files.readAllBytes(testDataDir.resolve("dummy/server_list.json")), + Files.readAllBytes(testDataDir.resolve("random.txt")), + Files.readAllBytes(testDataDir.resolve("server_list.json")), "server_list.json", Instant.EPOCH - )).code); + )); } @Test void testWrongKey() { - assertEquals(3, assertThrows(VerifyException.class, () -> + assertThrows(InvalidSignatureUnknownKeyException.class, () -> Discovery.verify( - Files.readAllBytes(testDataDir.resolve("dummy/server_list.json.wrong_key.minisig")), - Files.readAllBytes(testDataDir.resolve("dummy/server_list.json")), + Files.readAllBytes(testDataDir.resolve("server_list.json.wrong_key.minisig")), + Files.readAllBytes(testDataDir.resolve("server_list.json")), "server_list.json", Instant.EPOCH - )).code); + )); } @Test void testOldSignature() { - assertEquals(4, assertThrows(VerifyException.class, () -> + assertThrows(SignatureTooOldException.class, () -> Discovery.verify( - Files.readAllBytes(testDataDir.resolve("dummy/server_list.json.minisig")), - Files.readAllBytes(testDataDir.resolve("dummy/server_list.json")), + Files.readAllBytes(testDataDir.resolve("server_list.json.minisig")), + Files.readAllBytes(testDataDir.resolve("server_list.json")), "server_list.json", Instant.MAX - )).code); + )); } @Test void testUnknownExpectedFile() { assertThrows(IllegalArgumentException.class, () -> Discovery.verify( - Files.readAllBytes(testDataDir.resolve("dummy/other_list.json.minisig")), - Files.readAllBytes(testDataDir.resolve("dummy/other_list.json")), + Files.readAllBytes(testDataDir.resolve("other_list.json.minisig")), + Files.readAllBytes(testDataDir.resolve("other_list.json")), "other_list.json", Instant.EPOCH )); } -}
\ No newline at end of file +} diff --git a/wrappers/php/.gitignore b/wrappers/php/.gitignore index 4a56e6c..bdaa6e3 100644 --- a/wrappers/php/.gitignore +++ b/wrappers/php/.gitignore @@ -1,4 +1,5 @@ /vendor/ +/lib/* composer.phar .phpunit* *.h diff --git a/wrappers/php/Makefile b/wrappers/php/Makefile index 06c49f1..e0262e9 100644 --- a/wrappers/php/Makefile +++ b/wrappers/php/Makefile @@ -1,25 +1,51 @@ .PHONY: install-header test install-dev-dependencies clean -ifneq (clean,$(MAKECMDGOALS)) -include ../../exports/platform.mk +EXPORTS_PATH ?= ../../exports +EXPORTS_LIB_PATH ?= $(EXPORTS_PATH)/lib +ifneq ($(MAKECMDGOALS),clean) +include $(EXPORTS_PATH)/platform.mk + +# Add phpunit to PATH export PATH := $(abspath vendor/bin):$(PATH) endif +ifeq ($(COPY_LIB),1) +COPY_LIB_DIR = lib +endif + +ifneq ($(COPY_LIB_DIR),) +COPY_LIB_DIR := $(COPY_LIB_DIR)/ +endif + +# Strip / replace elements confusing PHP's limited C parser: __SIZE_TYPE__, _Complex, extern "C" +# Also add FFI_LIB library name, see https://www.php.net/manual/en/ffi.load install-header: - $(MAKE) -C ../../exports +ifneq ($(EXPORTS_PATH),) +ifneq ($(wildcard $(EXPORTS_PATH)/Makefile),) + $(MAKE) -C "$(EXPORTS_PATH)" +endif +endif mkdir -p src/headers sed --null-data \ -e 's/DO NOT EDIT/Modified for PHP/' \ + \ -e 's/__SIZE_TYPE__/size_t/g' \ -e 's/[^\n]*_Complex[^\n]*//g' \ -e 's/#ifdef __cplusplus[^#]*#endif//g' \ - -e 's/^/#define FFI_LIB "$(LIB_PREFIX)eduvpn_verify$(LIB_SUFFIX)"\n\n/' \ - "../../exports/$(GOOS)/$(GOARCH)/eduvpn_verify.h" > src/headers/eduvpn_verify_php.h + \ + -e 's/^/#define FFI_LIB "$(subst /,\/,$(COPY_LIB_DIR))$(LIB_FILE)"\n\n/' \ + \ + "$(EXPORTS_LIB_PATH)/$(GOOS)/$(GOARCH)/$(LIB_NAME).h" > src/headers/$(LIB_NAME)_php.h +ifeq ($(COPY_LIB),1) + install "$(EXPORTS_LIB_PATH)/$(GOOS)/$(GOARCH)/$(LIB_FILE)" -Dt "$(COPY_LIB_DIR)" +endif test: install-header install-dev-dependencies phpunit +# Try: composer, composer.phar, ./composer.phar, ./composer +# check-platform-reqs is needed because of config.platform in composer.json, see https://getcomposer.org/doc/06-config.md#platform install-dev-dependencies: if command -v composer; then \ composer install && composer check-platform-reqs; \ @@ -31,4 +57,4 @@ install-dev-dependencies: fi clean: - rm -rf vendor/ .phpunit* src/headers/*.h + rm -rf vendor/ .phpunit* src/headers/*.h lib/* diff --git a/wrappers/php/README.md b/wrappers/php/README.md index 776c0ac..b5cafa2 100644 --- a/wrappers/php/README.md +++ b/wrappers/php/README.md @@ -27,3 +27,9 @@ Or for the specified platform: ```shell make install-header GOOS=windows GOARCH=amd64 ``` + +When using this library, you will need to make sure that the linker can find the shared Go library. Alternatively, +pass `COPY_LIB=1` to `make install-header` to copy the library over to this folder and load it via this relative path. + +If you do not build this as part of the full repository, specify `EXPORTS_PATH="path/to/exports-folder"` when calling +make. This folder must contain `platform.mk` and the `lib/` folder with built libraries and headers. diff --git a/wrappers/php/src/Discovery.php b/wrappers/php/src/Discovery.php index 3ae7010..322d621 100644 --- a/wrappers/php/src/Discovery.php +++ b/wrappers/php/src/Discovery.php @@ -11,13 +11,15 @@ final class Discovery { public function __construct() { } + const LIB_NAME = "eduvpn_common"; + private static ?FFI $ffi = null; private static function ffi(): FFI { if (!self::$ffi) { - if (!(self::$ffi = FFI::load(__DIR__ . '/headers/eduvpn_verify_php.h'))) - throw new Error('failed to load eduvpn_verify'); + if (!(self::$ffi = FFI::load(__DIR__ . '/headers/' . self::LIB_NAME . '_php.h'))) + throw new Error('failed to load ' . self::LIB_NAME); } return self::$ffi; } @@ -30,8 +32,8 @@ final class Discovery * @param string $signedJson Signed .json file contents. * @param string $expectedFileName The file type to be verified, one of "server_list.json" or * "organization_list.json". - * @param int $minSignTime Minimum time for signature. Should be set to at least the time in a previously - * retrieved file. + * @param int $minSignTime Minimum time for signature. Should be set to at least the time of the previous + * signature. * @return void * @throws InvalidArgumentException If expectedFileName is not one of the allowed values. * @throws VerifyException If signature verification fails. diff --git a/wrappers/php/src/SignatureTooOldException.php b/wrappers/php/src/SignatureTooOldException.php index bbae949..4b7e341 100644 --- a/wrappers/php/src/SignatureTooOldException.php +++ b/wrappers/php/src/SignatureTooOldException.php @@ -2,7 +2,7 @@ namespace EduVpn\Common; -/** Signature has a timestamp lower than the specified minimum signing time. */ +/** Signature timestamp smaller than specified minimum signing time (rollback). */ final class SignatureTooOldException extends VerifyException { public function __construct() diff --git a/wrappers/php/tests/DiscoveryTest.php b/wrappers/php/tests/DiscoveryTest.php index 25ac187..fdce505 100644 --- a/wrappers/php/tests/DiscoveryTest.php +++ b/wrappers/php/tests/DiscoveryTest.php @@ -13,31 +13,31 @@ class DiscoveryTest extends TestCase public static function setUpBeforeClass(): void { - preg_match('/[\r\n](\S+)\s*/', file_get_contents(self::TEST_DATA_DIR . '/dummy/public.key'), $matches); + preg_match('/[\r\n](\S+)\s*/', file_get_contents(self::TEST_DATA_DIR . '/public.key'), $matches); Discovery::insecureTestingSetExtraKey($matches[1]); } public function testValid(): void { $this->expectNotToPerformAssertions(); - Discovery::verify(file_get_contents(self::TEST_DATA_DIR . '/dummy/server_list.json.minisig'), - file_get_contents(self::TEST_DATA_DIR . '/dummy/server_list.json'), + Discovery::verify(file_get_contents(self::TEST_DATA_DIR . '/server_list.json.minisig'), + file_get_contents(self::TEST_DATA_DIR . '/server_list.json'), 'server_list.json', 0); } public function testInvalidSignature(): void { $this->expectException(InvalidSignatureException::class); - Discovery::verify(file_get_contents(self::TEST_DATA_DIR . '/dummy/random.txt'), - file_get_contents(self::TEST_DATA_DIR . '/dummy/server_list.json'), + Discovery::verify(file_get_contents(self::TEST_DATA_DIR . '/random.txt'), + file_get_contents(self::TEST_DATA_DIR . '/server_list.json'), 'server_list.json', 0); } public function testWrongKey(): void { $this->expectException(InvalidSignatureUnknownKeyException::class); - Discovery::verify(file_get_contents(self::TEST_DATA_DIR . '/dummy/server_list.json.wrong_key.minisig'), - file_get_contents(self::TEST_DATA_DIR . '/dummy/server_list.json'), + Discovery::verify(file_get_contents(self::TEST_DATA_DIR . '/server_list.json.wrong_key.minisig'), + file_get_contents(self::TEST_DATA_DIR . '/server_list.json'), 'server_list.json', 0); } @@ -45,16 +45,16 @@ class DiscoveryTest extends TestCase public function testOldSignature(): void { $this->expectException(SignatureTooOldException::class); - Discovery::verify(file_get_contents(self::TEST_DATA_DIR . '/dummy/server_list.json.minisig'), - file_get_contents(self::TEST_DATA_DIR . '/dummy/server_list.json'), + Discovery::verify(file_get_contents(self::TEST_DATA_DIR . '/server_list.json.minisig'), + file_get_contents(self::TEST_DATA_DIR . '/server_list.json'), 'server_list.json', 1 << 31); } public function testUnknownExpectedFileName(): void { $this->expectException(InvalidArgumentException::class); - Discovery::verify(file_get_contents(self::TEST_DATA_DIR . '/dummy/other_list.json.minisig'), - file_get_contents(self::TEST_DATA_DIR . '/dummy/other_list.json'), + Discovery::verify(file_get_contents(self::TEST_DATA_DIR . '/other_list.json.minisig'), + file_get_contents(self::TEST_DATA_DIR . '/other_list.json'), 'other_list.json', 0); } } diff --git a/wrappers/python/Makefile b/wrappers/python/Makefile index be4beaa..ba4cf5f 100644 --- a/wrappers/python/Makefile +++ b/wrappers/python/Makefile @@ -1,15 +1,27 @@ .PHONY: pack test clean +EXPORTS_PATH ?= ../../exports +EXPORTS_LIB_PATH ?= $(EXPORTS_PATH)/lib + +ifneq ($(MAKECMDGOALS),clean) +include $(EXPORTS_PATH)/platform.mk +endif + ifdef PLAT_NAME SETUP_ARGS += --plat-name=$(PLAT_NAME) endif # Build for current platform only pack: - ./setup.py bdist_wheel $(SETUP_ARGS) + ./setup.py bdist_wheel $(SETUP_ARGS) --exports-lib-path="$(EXPORTS_LIB_PATH)" test: - $(MAKE) -C ../../exports copy-to COPY_TARGET=../wrappers/python/eduvpncommon/lib +ifneq ($(EXPORTS_PATH),) +ifneq ($(wildcard $(EXPORTS_PATH)/Makefile),) + $(MAKE) -C "$(EXPORTS_PATH)" +endif +endif + install "$(EXPORTS_LIB_PATH)/$(GOOS)/$(GOARCH)/$(LIB_FILE)" -Dt "eduvpncommon/lib" python3 -m unittest test_discovery rm eduvpncommon/lib/* diff --git a/wrappers/python/README.md b/wrappers/python/README.md index 6175910..bce492e 100644 --- a/wrappers/python/README.md +++ b/wrappers/python/README.md @@ -2,9 +2,7 @@ ## Requirements -Python 3.6+ is assumed, but it may work with older versions. - -TODO Build +Python 3.6+ is assumed, but it may work with older versions. To build, `setuptools` and `wheel` are required. ## Build & test @@ -16,7 +14,11 @@ Build wheel using library for current platform: make pack ``` -Build wheel using library for specified platform (passed to setuptools `--plat-name`): +(This does not build the shared Go library.) + +Build wheel using library for specified platform (passed to setuptools `--plat-name`, +see [`get_build_platform`](https://setuptools.pypa.io/en/latest/pkg_resources.html?highlight=get_build_platform#platform-utilities) +for more): ```shell make pack PLAT_NAME=win32 @@ -28,9 +30,12 @@ To install the wheel, run: pip install dist/eduvpncommon-[version]-py3-none-[platform].whl ``` -You could also reference the discovery module directly and copy the library for the platform to the `eduvpncommon/lib` +You could also reference the discovery module directly and copy the library for the platform to the `eduvpncommon/lib/` folder. +If you do not build this as part of the full repository, specify `EXPORTS_PATH="path/to/exports-folder"` when calling +make. This folder must contain `platform.mk` and the `lib/` folder with built libraries. + Test: ```shell diff --git a/wrappers/python/eduvpncommon/discovery.py b/wrappers/python/eduvpncommon/discovery.py index f7a312e..f22df58 100644 --- a/wrappers/python/eduvpncommon/discovery.py +++ b/wrappers/python/eduvpncommon/discovery.py @@ -15,28 +15,30 @@ _lib_suffixes = defaultdict(lambda: ".so", { _os = platform.system().lower() -_libname = f"{_lib_prefixes[_os]}eduvpn_verify{_lib_suffixes[_os]}" -_lib = cdll.LoadLibrary(str(pathlib.Path(__file__).parent / "lib" / _libname)) +_libname = "eduvpn_common" +_libfile = f"{_lib_prefixes[_os]}{_libname}{_lib_suffixes[_os]}" +# Library should have been copied to the lib/ folder +_lib = cdll.LoadLibrary(str(pathlib.Path(__file__).parent / "lib" / _libfile)) -class GoSlice(Structure): +class _GoSlice(Structure): _fields_ = [("data", POINTER(c_char)), ("len", c_int64), ("cap", c_int64)] @staticmethod - def make(bs: bytes) -> "GoSlice": - return GoSlice((c_char * len(bs))(*bs), len(bs), len(bs)) + def make(bs: bytes) -> "_GoSlice": + return _GoSlice((c_char * len(bs))(*bs), len(bs), len(bs)) -_lib.Verify.argtypes, _lib.Verify.restype = [GoSlice, GoSlice, GoSlice, c_uint64], c_int64 -_lib.InsecureTestingSetExtraKey.argtypes, _lib.InsecureTestingSetExtraKey.restype = [GoSlice], None +_lib.Verify.argtypes, _lib.Verify.restype = [_GoSlice, _GoSlice, _GoSlice, c_uint64], c_int64 +_lib.InsecureTestingSetExtraKey.argtypes, _lib.InsecureTestingSetExtraKey.restype = [_GoSlice], None class VerifyErrorCode(Enum): - ErrUnknownExpectedFileName = 1 # Expected file name is not one of the recognized values. + ErrUnknownExpectedFileName = 1 # Unknown expected file name specified. The signature has not been verified. ErrInvalidSignature = 2 # Signature is invalid (for the expected file type). ErrInvalidSignatureUnknownKey = 3 # Signature was created with an unknown key and has not been verified. - ErrTooOld = 4 # Signature has a timestamp lower than the specified minimum signing time. - Unknown = -1 # Other unknown error + ErrTooOld = 4 # Signature timestamp smaller than specified minimum signing time (rollback). + Unknown = -1 # Other unknown error. class VerifyError(Exception): @@ -44,6 +46,7 @@ class VerifyError(Exception): code_int: int # Original error code also for VerifyErrorCode.Unknown def __init__(self, err: int): + assert err try: self.code = VerifyErrorCode(err) except ValueError: @@ -68,13 +71,13 @@ def verify(signature: bytes, signed_json: bytes, expected_file_name: str, min_si :param signature: .minisig signature file contents. :param signed_json: Signed .json file contents. :param expected_file_name: The file type to be verified, one of "server_list.json" or "organization_list.json". - :param min_sign_time: Minimum time for signature. Should be set to at least the time in a previously retrieved file. + :param min_sign_time: Minimum time for signature. Should be set to at least the time of the previous signature. :raises VerifyException: If signature verification fails or expectedFileName is not one of the allowed values. """ - err = _lib.Verify(GoSlice.make(signature), GoSlice.make(signed_json), - GoSlice.make(expected_file_name.encode()), min_sign_time) + err = _lib.Verify(_GoSlice.make(signature), _GoSlice.make(signed_json), + _GoSlice.make(expected_file_name.encode()), min_sign_time) if err: raise VerifyError(err) @@ -82,4 +85,4 @@ def verify(signature: bytes, signed_json: bytes, expected_file_name: str, min_si def _insecure_testing_set_extra_key(key_string: str) -> None: """Use for testing only, see Go documentation.""" - _lib.InsecureTestingSetExtraKey(GoSlice.make(key_string.encode())) + _lib.InsecureTestingSetExtraKey(_GoSlice.make(key_string.encode())) diff --git a/wrappers/python/setup.py b/wrappers/python/setup.py index db254aa..9e7bde4 100755 --- a/wrappers/python/setup.py +++ b/wrappers/python/setup.py @@ -1,17 +1,20 @@ #!/usr/bin/env python3 import os -import pathlib import shutil +import sys import typing from collections import defaultdict -import sys from setuptools import setup from wheel.bdist_wheel import bdist_wheel as _bdist_wheel +_libname = "eduvpn_common" + def getlibpath(plat_name: str) -> typing.Union[str, None]: + """Get library path for plat_name relative to exports/lib/ folder.""" + _plat_map = defaultdict(lambda: plat_name, { "win32": "win-x86", }) @@ -47,12 +50,21 @@ def getlibpath(plat_name: str) -> typing.Union[str, None]: processed_os = _os_map[plat_os] return f"{processed_os}/{_arch_map[plat_arch]}/" \ - f"{_lib_prefixes[processed_os]}eduvpn_verify{_lib_suffixes[processed_os]}" + f"{_lib_prefixes[processed_os]}{_libname}{_lib_suffixes[processed_os]}" +# Adapted from https://stackoverflow.com/a/51794740 # You would say there would be a better way to do all of this, but I couldn't find it class bdist_wheel(_bdist_wheel): + user_options = _bdist_wheel.user_options + [ + ("exports-lib-path=", None, "path to exports/lib directory"), + ] + + def initialize_options(self): + super().initialize_options() + self.exports_lib_path = "../../exports/lib" # default + def run(self): self.plat_name_supplied = True # Force use platform @@ -63,9 +75,10 @@ class bdist_wheel(_bdist_wheel): print(f"Building wheel for platform {self.plat_name}") - shutil.copy2(f"../../exports/{libpath}", "eduvpncommon/lib/") + # setuptools will only use paths inside the package for package_data, so we copy the library + tmp_lib = shutil.copy2(f"{self.exports_lib_path}/{libpath}", "eduvpncommon/lib/") _bdist_wheel.run(self) - os.remove(f"eduvpncommon/lib/{pathlib.Path(libpath).name}") + os.remove(tmp_lib) setup( @@ -73,6 +86,6 @@ setup( version="0.1.0", packages=["eduvpncommon"], python_requires=">=3.6", - package_data={"eduvpncommon": ["lib/*eduvpn_verify*"]}, + package_data={"eduvpncommon": [f"lib/*{_libname}*"]}, cmdclass={"bdist_wheel": bdist_wheel}, ) diff --git a/wrappers/python/test_discovery.py b/wrappers/python/test_discovery.py index 1282a3e..73c51c4 100755 --- a/wrappers/python/test_discovery.py +++ b/wrappers/python/test_discovery.py @@ -14,21 +14,21 @@ def read_bytes(path: str) -> bytes: class VerifyTests(unittest.TestCase): @classmethod def setUpClass(cls) -> None: - with open(f"{test_data_dir}/dummy/public.key") as f: + with open(f"{test_data_dir}/public.key") as f: discovery._insecure_testing_set_extra_key(f.readlines()[-1][:-1]) def testValid(self): discovery.verify( - read_bytes(f"{test_data_dir}/dummy/server_list.json.minisig"), - read_bytes(f"{test_data_dir}/dummy/server_list.json"), + read_bytes(f"{test_data_dir}/server_list.json.minisig"), + read_bytes(f"{test_data_dir}/server_list.json"), "server_list.json", 0 ) def testValidMemoryView(self): discovery.verify( - read_bytes(f"{test_data_dir}/dummy/server_list.json.minisig"), - memoryview(b"abc" + read_bytes(f"{test_data_dir}/dummy/server_list.json") + b"abc")[3:-3], + read_bytes(f"{test_data_dir}/server_list.json.minisig"), + memoryview(b"abc" + read_bytes(f"{test_data_dir}/server_list.json") + b"abc")[3:-3], "server_list.json", 0 ) @@ -36,8 +36,8 @@ class VerifyTests(unittest.TestCase): def testInvalidSignature(self): with self.assertRaises(discovery.VerifyError) as ctx: discovery.verify( - read_bytes(f"{test_data_dir}/dummy/random.txt"), - read_bytes(f"{test_data_dir}/dummy/server_list.json"), + read_bytes(f"{test_data_dir}/random.txt"), + read_bytes(f"{test_data_dir}/server_list.json"), "server_list.json", 0 ) @@ -46,8 +46,8 @@ class VerifyTests(unittest.TestCase): def testWrongKey(self): with self.assertRaises(discovery.VerifyError) as ctx: discovery.verify( - read_bytes(f"{test_data_dir}/dummy/server_list.json.wrong_key.minisig"), - read_bytes(f"{test_data_dir}/dummy/server_list.json"), + read_bytes(f"{test_data_dir}/server_list.json.wrong_key.minisig"), + read_bytes(f"{test_data_dir}/server_list.json"), "server_list.json", 0 ) @@ -56,8 +56,8 @@ class VerifyTests(unittest.TestCase): def testOldSignature(self): with self.assertRaises(discovery.VerifyError) as ctx: discovery.verify( - read_bytes(f"{test_data_dir}/dummy/server_list.json.minisig"), - read_bytes(f"{test_data_dir}/dummy/server_list.json"), + read_bytes(f"{test_data_dir}/server_list.json.minisig"), + read_bytes(f"{test_data_dir}/server_list.json"), "server_list.json", 1 << 31 ) @@ -66,8 +66,8 @@ class VerifyTests(unittest.TestCase): def TestUnknownExpectedFile(self): with self.assertRaises(discovery.VerifyError) as ctx: discovery.verify( - read_bytes(f"{test_data_dir}/dummy/other_list.json.minisig"), - read_bytes(f"{test_data_dir}/dummy/other_list.json"), + read_bytes(f"{test_data_dir}/other_list.json.minisig"), + read_bytes(f"{test_data_dir}/other_list.json"), "other_list.json", 0 ) diff --git a/wrappers/swift/CEduVpnCommon/Sources/CEduVpnCommon/module.modulemap b/wrappers/swift/CEduVpnCommon/Sources/CEduVpnCommon/module.modulemap index c85e48f..2c50cfd 100644 --- a/wrappers/swift/CEduVpnCommon/Sources/CEduVpnCommon/module.modulemap +++ b/wrappers/swift/CEduVpnCommon/Sources/CEduVpnCommon/module.modulemap @@ -1,5 +1,5 @@ module CEduVpnCommon { - header "Headers/eduvpn_verify.h" - link "eduvpn_verify" + header "Headers/eduvpn_common.h" + link "eduvpn_common" export * } diff --git a/wrappers/swift/Makefile b/wrappers/swift/Makefile index 84b3cc1..b46a177 100644 --- a/wrappers/swift/Makefile +++ b/wrappers/swift/Makefile @@ -1,24 +1,33 @@ -.PHONY: build test clean +.PHONY: build test install-header clean -ifneq (clean,$(MAKECMDGOALS)) -include ../../exports/platform.mk +EXPORTS_PATH ?= ../../exports +EXPORTS_LIB_PATH ?= $(EXPORTS_PATH)/lib -ifeq (Windows_NT,$(OS)) +ifneq ($(MAKECMDGOALS),clean) +include $(EXPORTS_PATH)/platform.mk + +LIB_DIR = $(EXPORTS_LIB_PATH)/$(GOOS)/$(GOARCH) + +ifeq ($(OS),Windows_NT) SWIFT = ./swift.cmd else SWIFT = swift endif endif -build: .build_lib - $(SWIFT) build --configuration release -Xlinker -L"../../exports/$(GOOS)/$(GOARCH)" +build: install-header + $(SWIFT) build --configuration release -Xlinker -L"$(LIB_DIR)" + +test: install-header + $(SWIFT) test --parallel -Xlinker -L"$(LIB_DIR)" -test: .build_lib - $(SWIFT) test --parallel -Xlinker -L"../../exports/$(GOOS)/$(GOARCH)" +install-header: +ifneq ($(EXPORTS_PATH),) +ifneq ($(wildcard $(EXPORTS_PATH)/Makefile),) + $(MAKE) -C "$(EXPORTS_PATH)" +endif +endif + install "$(LIB_DIR)/$(LIB_NAME).h" -Dt CEduVpnCommon/Sources/CEduVpnCommon/Headers # Copy header for modulemap clean: rm -rf .build/ CEduVpnCommon/Sources/CEduVpnCommon/Headers/*.h - -.build_lib: - $(MAKE) -C ../../exports - install "../../exports/$(GOOS)/$(GOARCH)/eduvpn_verify.h" -Dt CEduVpnCommon/Sources/CEduVpnCommon/Headers diff --git a/wrappers/swift/README.md b/wrappers/swift/README.md index 8259592..f28b028 100644 --- a/wrappers/swift/README.md +++ b/wrappers/swift/README.md @@ -2,7 +2,8 @@ ## Requirements -You will need to install the [Swift SDK](https://www.swift.org/getting-started), which includes the `swift` tool. +You will need to install the [Swift SDK](https://www.swift.org/getting-started), which includes the `swift` tool. This +project does not require Xcode as it uses the Swift Package Manager. ## Build & test @@ -18,7 +19,22 @@ Build `EduVpnCommon` using shared Go library for specified platform, e.g.: make GOOS=linux GOARCH=amd64 ``` -On Windows, you will also need to generate a .lib for the .dll. +When using this library, you will need to make sure that the linker can find the shared Go library. + +<small>On Windows, you will also need to generate a .lib import library for the .dll. You can +use `exports/generate_lib.ps1` +for this, passing in the path to the DLL file. Execute this from a Visual Studio Developer shell before building the +Swift project. Alternatively, you could use `objdump` and `llvm-dlltool`. You only need to update this if the list of +exported symbols changes.</small> + +If you just want to copy over the C header file to the right directory for the modulemap in `CEduVpnCommon`, run: + +```shell +make install-header +``` + +If you do not build this as part of the full repository, specify `EXPORTS_PATH="path/to/exports-folder"` when calling +make. This folder must contain `platform.mk` and the `lib/` folder with built libraries and headers. Test: diff --git a/wrappers/swift/Sources/EduVpnCommon/EduVpnCommon.swift b/wrappers/swift/Sources/EduVpnCommon/EduVpnCommon.swift index 340e94a..b849626 100644 --- a/wrappers/swift/Sources/EduVpnCommon/EduVpnCommon.swift +++ b/wrappers/swift/Sources/EduVpnCommon/EduVpnCommon.swift @@ -9,7 +9,7 @@ private extension Data { // This closure method guarantees this try withUnsafeBytes { (pointer: UnsafeRawBufferPointer) -> ResultType in // Note: UnsafeRawBufferPointer.startIndex will always be 0, see docs - // Cast to UnsafeMutableRawPointer, assumes it will not be written to + // Cast to UnsafeMutableRawPointer, assumes it will not actually be written to try body(GoSlice(data: UnsafeMutableRawPointer(mutating: pointer.baseAddress), len: GoInt(pointer.count), cap: GoInt(pointer.count))) } @@ -33,9 +33,9 @@ public enum VerifyErr: Error, Equatable { /// Signature has a timestamp lower than the specified minimum signing time. case ErrTooOld /// Other unknown error - case Unknown(code: GoInt) + case Unknown(code: GoInt8) - static func fromCode(_ code: GoInt) -> VerifyErr { + static func fromCode(_ code: GoInt8) -> VerifyErr { precondition(code != 0) switch code { case 1: return ErrUnknownExpectedFileName @@ -54,7 +54,7 @@ public enum VerifyErr: Error, Equatable { /// - signature: .minisig signature file contents. /// - signedJson: Signed .json file contents. /// - expectedFileName: The file type to be verified, one of "server_list.json" or "organization_list.json". -/// - minSignTime: Minimum time for signature. Should be set to at least the time in a previously retrieved file. +/// - minSignTime: Minimum time for signature. Should be set to at least the time of the previous signature. /// - Throws: VerifyErr: If signature verification fails or `expectedFileName` is not one of the allowed values. public func Verify(signature: Data, signedJson: Data, expectedFileName: String, minSignTime: Date) throws { let result = signature.withSlice { signatureData in diff --git a/wrappers/swift/Tests/EduVpnCommonTests/EduVpnCommonTests.swift b/wrappers/swift/Tests/EduVpnCommonTests/EduVpnCommonTests.swift index a508023..21186a9 100644 --- a/wrappers/swift/Tests/EduVpnCommonTests/EduVpnCommonTests.swift +++ b/wrappers/swift/Tests/EduVpnCommonTests/EduVpnCommonTests.swift @@ -6,14 +6,14 @@ final class EduVpnCommonTests: XCTestCase { override class func setUp() { // Swift is confused by CRLF, so on some systems we cannot just take the second-to-last element - InsecureTestingSetExtraKey(keyString: try! String(contentsOfFile: "\(testDataDir)/dummy/public.key") + InsecureTestingSetExtraKey(keyString: try! String(contentsOfFile: "\(testDataDir)/public.key") .components(separatedBy: .newlines).last(where: { !$0.isEmpty })!) } func testValid() throws { try Verify( - signature: try! Data(contentsOf: URL(fileURLWithPath: "\(EduVpnCommonTests.testDataDir)/dummy/server_list.json.minisig")), - signedJson: try! Data(contentsOf: URL(fileURLWithPath: "\(EduVpnCommonTests.testDataDir)/dummy/server_list.json")), + signature: try! Data(contentsOf: URL(fileURLWithPath: "\(EduVpnCommonTests.testDataDir)/server_list.json.minisig")), + signedJson: try! Data(contentsOf: URL(fileURLWithPath: "\(EduVpnCommonTests.testDataDir)/server_list.json")), expectedFileName: "server_list.json", minSignTime: Date(timeIntervalSince1970: 0)) } @@ -21,8 +21,8 @@ final class EduVpnCommonTests: XCTestCase { func testInvalidSignature() throws { XCTAssertThrowsError( try Verify( - signature: try! Data(contentsOf: URL(fileURLWithPath: "\(EduVpnCommonTests.testDataDir)/dummy/random.txt")), - signedJson: try! Data(contentsOf: URL(fileURLWithPath: "\(EduVpnCommonTests.testDataDir)/dummy/server_list.json")), + signature: try! Data(contentsOf: URL(fileURLWithPath: "\(EduVpnCommonTests.testDataDir)/random.txt")), + signedJson: try! Data(contentsOf: URL(fileURLWithPath: "\(EduVpnCommonTests.testDataDir)/server_list.json")), expectedFileName: "server_list.json", minSignTime: Date(timeIntervalSince1970: 0)), "", {err in XCTAssertEqual(err as? VerifyErr, VerifyErr.ErrInvalidSignature)}); @@ -31,8 +31,8 @@ final class EduVpnCommonTests: XCTestCase { func testWrongKey() throws { XCTAssertThrowsError( try Verify( - signature: try! Data(contentsOf: URL(fileURLWithPath: "\(EduVpnCommonTests.testDataDir)/dummy/server_list.json.wrong_key.minisig")), - signedJson: try! Data(contentsOf: URL(fileURLWithPath: "\(EduVpnCommonTests.testDataDir)/dummy/server_list.json")), + signature: try! Data(contentsOf: URL(fileURLWithPath: "\(EduVpnCommonTests.testDataDir)/server_list.json.wrong_key.minisig")), + signedJson: try! Data(contentsOf: URL(fileURLWithPath: "\(EduVpnCommonTests.testDataDir)/server_list.json")), expectedFileName: "server_list.json", minSignTime: Date(timeIntervalSince1970: 0)), "", {err in XCTAssertEqual(err as? VerifyErr, VerifyErr.ErrInvalidSignatureUnknownKey)}); @@ -41,8 +41,8 @@ final class EduVpnCommonTests: XCTestCase { func testOldSignature() throws { XCTAssertThrowsError( try Verify( - signature: try! Data(contentsOf: URL(fileURLWithPath: "\(EduVpnCommonTests.testDataDir)/dummy/server_list.json.minisig")), - signedJson: try! Data(contentsOf: URL(fileURLWithPath: "\(EduVpnCommonTests.testDataDir)/dummy/server_list.json")), + signature: try! Data(contentsOf: URL(fileURLWithPath: "\(EduVpnCommonTests.testDataDir)/server_list.json.minisig")), + signedJson: try! Data(contentsOf: URL(fileURLWithPath: "\(EduVpnCommonTests.testDataDir)/server_list.json")), expectedFileName: "server_list.json", minSignTime: Date(timeIntervalSince1970: TimeInterval(1 << 31))), "", {err in XCTAssertEqual(err as? VerifyErr, VerifyErr.ErrTooOld)}); @@ -51,8 +51,8 @@ final class EduVpnCommonTests: XCTestCase { func testUnknownExpectedFile() throws { XCTAssertThrowsError( try Verify( - signature: try! Data(contentsOf: URL(fileURLWithPath: "\(EduVpnCommonTests.testDataDir)/dummy/other_list.json.minisig")), - signedJson: try! Data(contentsOf: URL(fileURLWithPath: "\(EduVpnCommonTests.testDataDir)/dummy/other_list.json")), + signature: try! Data(contentsOf: URL(fileURLWithPath: "\(EduVpnCommonTests.testDataDir)/other_list.json.minisig")), + signedJson: try! Data(contentsOf: URL(fileURLWithPath: "\(EduVpnCommonTests.testDataDir)/other_list.json")), expectedFileName: "other_list.json", minSignTime: Date(timeIntervalSince1970: 0)), "", {err in XCTAssertEqual(err as? VerifyErr, VerifyErr.ErrUnknownExpectedFileName)}); diff --git a/wrappers/swift/swift.cmd b/wrappers/swift/swift.cmd index 87fba4b..57040bd 100755 --- a/wrappers/swift/swift.cmd +++ b/wrappers/swift/swift.cmd @@ -1,6 +1,6 @@ @echo off -:: Rename PATH -> Path +:: Rename PATH -> Path because of swift issue https://github.com/compnerd/swift-build/issues/413 set _p=%PATH% set PATH= set Path=%_p% |
