This is an automated email from the ASF dual-hosted git repository.

jbonofre pushed a commit to branch karaf-4.2.x
in repository https://gitbox.apache.org/repos/asf/karaf.git


The following commit(s) were added to refs/heads/karaf-4.2.x by this push:
     new 0d6ee2c  [KARAF-6350] - Add support for elliptic keys in the 
PublicKeyLoginModule
0d6ee2c is described below

commit 0d6ee2cbc485af4eadd353f0900f586bab4a406a
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Tue Jun 25 13:51:07 2019 +0100

    [KARAF-6350] - Add support for elliptic keys in the PublicKeyLoginModule
---
 .../jaas/modules/ldap/LDAPPubkeyLoginModule.java   |   3 +-
 .../publickey/PublickeyBackingEngineFactory.java   |   6 +-
 .../modules/publickey/PublickeyLoginModule.java    | 141 +++++++---
 .../modules/publickey/PublicKeyEncodingTest.java   | 212 +++++++++++++++
 .../publickey/PublicKeyLoginModuleTest.java        | 287 +++++++++++++++++++++
 .../karaf/jaas/modules/publickey/pubkey.properties |  20 ++
 .../karaf/jaas/modules/publickey/pubkey.users      |  23 ++
 7 files changed, 652 insertions(+), 40 deletions(-)

diff --git 
a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/ldap/LDAPPubkeyLoginModule.java
 
b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/ldap/LDAPPubkeyLoginModule.java
index b66f78a..b3772bf 100644
--- 
a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/ldap/LDAPPubkeyLoginModule.java
+++ 
b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/ldap/LDAPPubkeyLoginModule.java
@@ -136,9 +136,8 @@ public class LDAPPubkeyLoginModule extends 
AbstractKarafLoginModule {
             throw new FailedLoginException("no public key supplied by the 
client");
         String[] storedKeys = cache.getUserPubkeys(userDn);
         if (storedKeys.length > 0) {
-            String keyString = PublickeyLoginModule.getString(key);
             for (String storedKey : storedKeys) {
-                if (keyString.equals(storedKey)) {
+                if (PublickeyLoginModule.equals(key, storedKey)) {
                     return;
                 }
             }
diff --git 
a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/publickey/PublickeyBackingEngineFactory.java
 
b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/publickey/PublickeyBackingEngineFactory.java
index 70f11db..663d228 100644
--- 
a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/publickey/PublickeyBackingEngineFactory.java
+++ 
b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/publickey/PublickeyBackingEngineFactory.java
@@ -32,18 +32,16 @@ public class PublickeyBackingEngineFactory implements 
BackingEngineFactory {
     private static final String USER_FILE = "users";
 
     public BackingEngine build(Map<String, ?> options) {
-        PublickeyBackingEngine engine = null;
         String usersFile = (String) options.get(USER_FILE);
 
         File f = new File(usersFile);
-        Properties users;
         try {
-            users = new Properties(f);
+            Properties users = new Properties(f);
             return new PublickeyBackingEngine(users);
         } catch (IOException ioe) {
             logger.warn("Cannot open keys file:" + usersFile);
         }
-        return engine;
+        return null;
     }
 
     public String getModuleClass() {
diff --git 
a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/publickey/PublickeyLoginModule.java
 
b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/publickey/PublickeyLoginModule.java
index 4c45861..644fa4f 100644
--- 
a/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/publickey/PublickeyLoginModule.java
+++ 
b/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/publickey/PublickeyLoginModule.java
@@ -15,15 +15,31 @@
  */
 package org.apache.karaf.jaas.modules.publickey;
 
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
 import java.io.File;
 import java.io.IOException;
 import java.math.BigInteger;
+import java.nio.charset.StandardCharsets;
+import java.security.AlgorithmParameters;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
 import java.security.PublicKey;
 import java.security.interfaces.DSAPublicKey;
+import java.security.interfaces.ECPublicKey;
 import java.security.interfaces.RSAKey;
-import java.security.interfaces.RSAPublicKey;
+import java.security.spec.DSAPublicKeySpec;
+import java.security.spec.ECGenParameterSpec;
+import java.security.spec.ECParameterSpec;
+import java.security.spec.ECPoint;
+import java.security.spec.ECPublicKeySpec;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.InvalidParameterSpecException;
+import java.security.spec.KeySpec;
+import java.security.spec.RSAPublicKeySpec;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import javax.security.auth.Subject;
@@ -43,14 +59,31 @@ import 
org.apache.karaf.jaas.modules.AbstractKarafLoginModule;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import static 
org.apache.karaf.jaas.modules.encryption.BasicEncryption.base64Encode;
-
 public class PublickeyLoginModule extends AbstractKarafLoginModule {
 
     private final Logger LOG = 
LoggerFactory.getLogger(PublickeyLoginModule.class);
 
     private static final String USERS_FILE = "users";
+    private static final Map<String, String> nistSecMap;
+
+    static {
+        // From RFC-5656
+        Map<String, String> map = new HashMap<>();
+        map.put("nistp256", "secp256r1");
+        map.put("nistp384", "secp384r1");
+        map.put("nistp521", "secp521r1");
+        map.put("1.3.132.0.1", "sect163k1");
+        map.put("1.2.840.10045.3.1.1", "secp192r1");
+        map.put("1.3.132.0.33", "secp224r1");
+        map.put("1.3.132.0.26", "sect233k1");
+        map.put("1.3.132.0.27", "sect233r1");
+        map.put("1.3.132.0.16", "sect283k1");
+        map.put("1.3.132.0.36", "sect409k1");
+        map.put("1.3.132.0.37", "sect409r1");
+        map.put("1.3.132.0.38", "sect571k1");
 
+        nistSecMap = Collections.unmodifiableMap(map);
+    }
     private String usersFile;
 
     public void initialize(Subject subject, CallbackHandler callbackHandler, 
Map<String, ?> sharedState, Map<String, ?> options) {
@@ -110,7 +143,7 @@ public class PublickeyLoginModule extends 
AbstractKarafLoginModule {
         String storedKey = infos[0];
 
         // check the provided password
-        if (!getString(key).equals(storedKey)) {
+        if (!equals(key, storedKey)) {
             if (!this.detailedLoginExcepion) {
                 throw new FailedLoginException("login failed");
             } else {
@@ -146,46 +179,86 @@ public class PublickeyLoginModule extends 
AbstractKarafLoginModule {
         return true;
     }
 
-    public static String getString(PublicKey key) throws FailedLoginException {
+    public static boolean equals(PublicKey key, String storedKey) throws 
FailedLoginException {
         try {
+            DataInputStream dis = new DataInputStream(new 
ByteArrayInputStream(Base64.getDecoder().decode(storedKey)));
+            String identifier = readString(dis);
             if (key instanceof DSAPublicKey) {
-                DSAPublicKey dsa = (DSAPublicKey) key;
-                ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                DataOutputStream dos = new DataOutputStream(baos);
-                write(dos, "ssh-dss");
-                write(dos, dsa.getParams().getP());
-                write(dos, dsa.getParams().getQ());
-                write(dos, dsa.getParams().getG());
-                write(dos, dsa.getY());
-                dos.close();
-                return base64Encode(baos.toByteArray());
+                if (!"ssh-dss".equals(identifier)) {
+                    return false;
+                }
+
+                BigInteger p = readBigInteger(dis);
+                BigInteger q = readBigInteger(dis);
+                BigInteger g = readBigInteger(dis);
+                BigInteger y = readBigInteger(dis);
+
+                KeyFactory keyFactory = KeyFactory.getInstance("DSA");
+                KeySpec publicKeySpec = new DSAPublicKeySpec(y, p, q, g);
+                PublicKey generatedPublicKey = 
keyFactory.generatePublic(publicKeySpec);
+
+                return key.equals(generatedPublicKey);
             } else if (key instanceof RSAKey) {
-                RSAPublicKey rsa = (RSAPublicKey) key;
-                ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                DataOutputStream dos = new DataOutputStream(baos);
-                write(dos, "ssh-rsa");
-                write(dos, rsa.getPublicExponent());
-                write(dos, rsa.getModulus());
-                dos.close();
-                return base64Encode(baos.toByteArray());
+                if (!"ssh-rsa".equals(identifier)) {
+                    return false;
+                }
+
+                BigInteger exponent = readBigInteger(dis);
+                BigInteger modulus = readBigInteger(dis);
+
+                KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+                KeySpec publicKeySpec = new RSAPublicKeySpec(modulus, 
exponent);
+                PublicKey generatedPublicKey = 
keyFactory.generatePublic(publicKeySpec);
+
+                return key.equals(generatedPublicKey);
+            } else if (key instanceof ECPublicKey) {
+                String ecIdentifier = readString(dis);
+                if (!identifier.equals("ecdsa-sha2-" + ecIdentifier)
+                    || !nistSecMap.containsKey(ecIdentifier)) {
+                    return false;
+                }
+
+                // Overall size of the x + y coordinates. We only support 
uncompressed points here, so
+                // to read x + y we ignore the "04" byte using (size - 1) / 2
+                int size = dis.readInt();
+                byte[] bytes = new byte[(size - 1) / 2];
+
+                dis.skipBytes(1);
+                dis.read(bytes, 0, bytes.length);
+                BigInteger x = new BigInteger(bytes);
+
+                dis.read(bytes, 0, bytes.length);
+                BigInteger y = new BigInteger(bytes);
+
+                KeyFactory keyFactory = KeyFactory.getInstance("EC");
+                AlgorithmParameters parameters = 
AlgorithmParameters.getInstance("EC");
+                parameters.init(new 
ECGenParameterSpec(nistSecMap.get(ecIdentifier)));
+                ECParameterSpec ecParameters = 
parameters.getParameterSpec(ECParameterSpec.class);
+                ECPoint pubPoint = new ECPoint(x, y);
+                KeySpec keySpec = new ECPublicKeySpec(pubPoint, ecParameters);
+                PublicKey generatedPublicKey = 
keyFactory.generatePublic(keySpec);
+
+                return key.equals(generatedPublicKey);
             } else {
                 throw new FailedLoginException("Unsupported key type " + 
key.getClass().toString());
             }
-        } catch (IOException e) {
+        } catch (IOException | NoSuchAlgorithmException | 
InvalidKeySpecException | InvalidParameterSpecException e) {
             throw new FailedLoginException("Unable to check public key");
         }
     }
 
-    private static void write(DataOutputStream dos, BigInteger integer) throws 
IOException {
-        byte[] data = integer.toByteArray();
-        dos.writeInt(data.length);
-        dos.write(data, 0, data.length);
+    private static String readString(DataInputStream dis) throws IOException {
+        int size = dis.readInt();
+        byte[] bytes = new byte[size];
+        dis.read(bytes, 0, bytes.length);
+        return new String(bytes, StandardCharsets.UTF_8);
     }
 
-    private static void write(DataOutputStream dos, String str) throws 
IOException {
-        byte[] data = str.getBytes();
-        dos.writeInt(data.length);
-        dos.write(data);
+    private static BigInteger readBigInteger(DataInputStream dis) throws 
IOException {
+        int size = dis.readInt();
+        byte[] bytes = new byte[size];
+        dis.read(bytes, 0, bytes.length);
+        return new BigInteger(bytes);
     }
 
 }
diff --git 
a/jaas/modules/src/test/java/org/apache/karaf/jaas/modules/publickey/PublicKeyEncodingTest.java
 
b/jaas/modules/src/test/java/org/apache/karaf/jaas/modules/publickey/PublicKeyEncodingTest.java
new file mode 100644
index 0000000..e85304f
--- /dev/null
+++ 
b/jaas/modules/src/test/java/org/apache/karaf/jaas/modules/publickey/PublicKeyEncodingTest.java
@@ -0,0 +1,212 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.jaas.modules.publickey;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.math.BigInteger;
+import java.security.AlgorithmParameters;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.security.spec.DSAPublicKeySpec;
+import java.security.spec.ECGenParameterSpec;
+import java.security.spec.ECParameterSpec;
+import java.security.spec.ECPoint;
+import java.security.spec.ECPublicKeySpec;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.InvalidParameterSpecException;
+import java.security.spec.KeySpec;
+import java.security.spec.RSAPublicKeySpec;
+
+import javax.security.auth.login.FailedLoginException;
+
+import org.junit.Test;
+
+public class PublicKeyEncodingTest {
+
+    @Test
+    public void testRSAKeys() throws FailedLoginException, 
NoSuchAlgorithmException, InvalidKeySpecException {
+        // Generated using: ssh-keygen -t rsa
+        String storedKey = 
"AAAAB3NzaC1yc2EAAAADAQABAAABAQDGX4CpCL49sWHaIuDE4VbGkdTMhsDLV3b8MDZ37Llsx3kRBs/x7G3OhSvQPhI"
+            + 
"jMNcbnUnCr+6O6poKjRcFI1Aj76TiSSYlvz9QbsWqc50ZwCuR39h6F9u8f9k62AV7IVA4aNVSJBFn2nOA00HOWvDDrU3ykG0cPeJcmP1l"
+            + 
"PeOO9WJVG7dc37v3soZZniIH+uop/UFQ4Ga0zWy4xjggAy2rE2p0BYHchrJb43ovInh5cGgXx2vNVwURsAf0TAPJwn7GLNpMYr3IFbRC3"
+            + 
"Tbe1wPdy9YM4rFlKL78o/dFbvUOH+Vd1BlYDofoxT4kHxod7W5wPALBr/Bm8CD2tR6OLLoD";
+        String knownModulus = 
"2504227846033126752625313329217708474924890377669312098933267135871562327792150810915433595733"
+            + 
"979130785790337621243914845149325143098632580183245971502051291613503136182182218708721890923769091345704"
+            + 
"119963221758691543226829294312457492456071842409242817598014777158790065648435489978774648853589909638928"
+            + 
"448069481622573966178879417253888452317622624006445863588961367514293886664167742695648199055900918338245"
+            + 
"701727653606086096756173044470526840851957391900922886984556493506186438991284463663361749451775578708454"
+            + 
"0181594148839238901052763862484299588887844606103377160953183624788815045644521767391398467190125279747";
+
+        // Generate a PublicKey using the known values
+        BigInteger modulus = new BigInteger(knownModulus);
+        BigInteger exponent = new BigInteger("65537");
+        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+        KeySpec publicKeySpec = new RSAPublicKeySpec(modulus, exponent);
+        PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
+
+        assertTrue(PublickeyLoginModule.equals(publicKey, storedKey));
+
+        // Make sure a different stored key does not work
+        String differentKey = 
"AAAAB3NzaC1yc2EAAAADAQABAAABAQC9nIk6uBMouH2KhMZnnVhkEGC7ZdSOHZbCcmQSsvK3bl/Ly2yzvXNdqqRhlyv"
+            + 
"Lv/Qjq0i4HnZsOUFAsfarYh8A0IP238AhTCoAeZf+ga+Mpm2uc+AOgDzwupfMYs6Zz81HWr1UsDr+LCOJkCC1/zzh5lub/Obif49j+nC1XX"
+            + 
"0fT0AJ9BeGnR9HWg3m72SCUmWYMSYGwgfjNqTtqA9IHxCfEr29J8YO7HiJME3zwj0ok133RuZASEclTYXtJkKYvAzE6obhBPw7J6kqETJIH"
+            + 
"0G0SkNjIm7cWThBalzyqcfydZ+0O+f/3LuSSp7EawaKu3g8mHkjt8b8ZxtjhgY0BZNV";
+        assertFalse(PublickeyLoginModule.equals(publicKey, differentKey));
+    }
+
+    @Test
+    public void testRSA1024() throws FailedLoginException, 
NoSuchAlgorithmException, InvalidKeySpecException {
+        // Generated using: ssh-keygen -t rsa -b 1024
+        String storedKey = 
"AAAAB3NzaC1yc2EAAAADAQABAAAAgQCpvuUWHwGUbRtunzgNaiKo9varvw3rZ6xRwV37/tNsMcdE98T07zF3UiUzfm79vv"
+            + 
"u6LrsMX6yzR3j1hSKxGtHoCuLO+wdx20Cxn+aqDsQsjTEgOE3SnqUhqX0aFRWs9GUo2sXRZooR7+5EKhSzFTmkgmx0b/FhlJQ2/Bdc9woZAw==";
+        String knownModulus = 
"1191994723232881252194746074531692276628392720352218105656446277364105948933208899459090143"
+            + 
"34485583082055798404847857986526198262831735131892900109314572095535330090724020090628526184947685186417937"
+            + 
"713630451839747221181072495928766941603698696083904958230358940260930311021743608730447712164571127205526640899";
+
+        // Generate a PublicKey using the known values
+        BigInteger modulus = new BigInteger(knownModulus);
+        BigInteger exponent = new BigInteger("65537");
+        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+        KeySpec publicKeySpec = new RSAPublicKeySpec(modulus, exponent);
+        PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
+
+        assertTrue(PublickeyLoginModule.equals(publicKey, storedKey));
+
+        // Make sure a different stored key does not work
+        String differentKey = 
"AAAAB3NzaC1yc2EAAAADAQABAAABAQC9nIk6uBMouH2KhMZnnVhkEGC7ZdSOHZbCcmQSsvK3bl/Ly2yzvXNdqqRhlyv"
+            + 
"Lv/Qjq0i4HnZsOUFAsfarYh8A0IP238AhTCoAeZf+ga+Mpm2uc+AOgDzwupfMYs6Zz81HWr1UsDr+LCOJkCC1/zzh5lub/Obif49j+nC1XX"
+            + 
"0fT0AJ9BeGnR9HWg3m72SCUmWYMSYGwgfjNqTtqA9IHxCfEr29J8YO7HiJME3zwj0ok133RuZASEclTYXtJkKYvAzE6obhBPw7J6kqETJIH"
+            + 
"0G0SkNjIm7cWThBalzyqcfydZ+0O+f/3LuSSp7EawaKu3g8mHkjt8b8ZxtjhgY0BZNV";
+        assertFalse(PublickeyLoginModule.equals(publicKey, differentKey));
+    }
+
+    @Test
+    public void testDSA() throws FailedLoginException, 
NoSuchAlgorithmException, InvalidKeySpecException {
+        // Generated using: ssh-keygen -t dsa
+        String storedKey = 
"AAAAB3NzaC1kc3MAAACBAJlAn/bPWpugKCLyoQpe8AbSZiIxdEJhl+VV8YEH6jfb9lLPA9JkQAf/lnG1Jx01UM65RRyKtnMAiB"
+            + 
"pkhrPy3DbqJ4FgYBmc1Sdiufomilq6zSbE0esJEMyxEvSNDQLqIiUcSwVyJJj1vpV6ZPA6ihipTIaiSV+rmfKcS05i27UlAAAAFQCg3ZtIytPmG"
+            + 
"ILQ7OEifIJvCSlS5QAAAIBUbgpjk7vSWVNICgKG6OrXeK0kJYRG6AaUZSiB2neoABMyGIHQ8dBCk+jtYqRMYyoc+OPi5q43VcDMxgzR/cHGjZi6"
+            + 
"0w/I3M83072dAdaoi0cleL/V8NaH+SOvkkYkAG57OIa3ly9PVpPfeXRnbbjkz1EsrvXIelqb5enLhlIgXgAAAIA11rUkN/J3K7nw/BiolhpZR3M"
+            + 
"VhWWIJFjJyU7ZC0yO8a+3AExuhTI6YQvsyvlY69KCwAwZsZvx9DryDE5xTfhzYa5kV4mM4AJSrE8/GtxLUVPZLwV6eoZLv1RIqP543ihZtoFyVm"
+            + "MaTQFj45Qo8uAuVDjx5mpk/Rk1pYPUd0lc1Q==";
+        String p = 
"1076175237625726563105954460741409330556298182412863930703571469202992312952487088821612089126846931217220"
+            + 
"139938550642040962241586994856559462488140821681403960733982209827487135132210000913512532065787125116985685638"
+            + 
"40437219296134522589816052156357553531846010339651017908589163855315552516201352809575855397";
+        String q = "918380515194943729419256231914804453973955269349";
+        String g = 
"5928865413019314795162062081939159959737363875586187627523617102819491716184351195073908492559564825805562"
+            + 
"104476892066919492044841627907376461274343797017375757242038772707578284292374846844427026690399002493750530347"
+            + 
"2378225083646830569532678306021077676137269211638266431262139218141967811197461432032698462";
+        String y = 
"3780682190459260799543888842390974417268312111951424991203659597814001671832656608276823896973755971735795"
+            + 
"130565245682634187551545737028902938478313465290457154458005480679650487421678748598551351730312164280338152996"
+            + 
"0448119336850459047721615478019482431582683540283279032651976075781966545889409150149549269";
+
+        // Generate a PublicKey using the known values
+        KeyFactory keyFactory = KeyFactory.getInstance("DSA");
+        KeySpec publicKeySpec = new DSAPublicKeySpec(new BigInteger(y), new 
BigInteger(p), new BigInteger(q), new BigInteger(g));
+        PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
+
+        assertTrue(PublickeyLoginModule.equals(publicKey, storedKey));
+
+        // Make sure a different stored key does not work
+        String differentKey = 
"AAAAB3NzaC1kc3MAAACBALE+qmsDN5lJYqQUmtrM7RI4vFcAQnla7Jp8Qy5ZUf63IFEA+tDzareKZOadwYbHOrIq3bDFCMH"
+            + 
"HIVvFWJNhcJUBH8ZZnk7942Sxg6P5B3OQlCC6O4ADpe6NmwsxCpjpkyJizWTwvTspE6vV32VMa70UJlL1OtymgsWDef8ZQKqBAAAAFQCwiMFuOv"
+            + 
"t6AZ1PgOwytbS1ra/FswAAAIAvf9b+K6eF6Mx3CnUVMHVldK4VybXjn/GwARH7BG8HJ8aGmMLvhk2qKGN5NatxgAc6IzRcwFbKvtniTTh06seuY"
+            + 
"CwIvHs+7nldZ255D23as90jAqstkBGt5NmX5R/TgHQPwQILJpydaYUEf6f/KU6MZPANo8cbEi2hxgljWCQcwAAAAIEAh2S+0V+64AZy8+T03eMX"
+            + 
"yBmt4xn8JPJzIHizF4VeUpTVwyA2EsiG9/YEWEGATj7mAcfAmLKl5rV1tQdXgUl2uxCDXw91c9PrYbfrHJjD1Oj6xHOjExDZI31Z8S6OKwo7df7"
+            + "0GumGSDsg0nibs5rEwkkcT64AOMn1o4JvabsP200=";
+        assertFalse(PublickeyLoginModule.equals(publicKey, differentKey));
+    }
+
+    @Test
+    public void testEC521() throws FailedLoginException, 
NoSuchAlgorithmException, InvalidKeySpecException, 
InvalidParameterSpecException {
+        // ecdsa-sha2-nistp521 - generated using: ssh-keygen -t ecdsa -b 521
+        String storedKey = 
"AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBADLxNQ1lf99/8WlEg1nYbDL+qcWY4KSFZG+"
+            + 
"2euZ1hAO9m1ly4ByuqLhuf1M3JPhhOCMIn9ihrPcxplG2zjpOnhaugDdwGJn+qcwkZSXVWoZOxpYUaQRdfnSd5wAKo9XOPqvc/L3BeHK"
+            + "mPPygLH7eW2MEz2qOWe7Bby9duELK+9Zn3ebOQ==";
+        String x = 
"273209377797440455675669012133614826094878213786507845287169633163915658072657502796285437529808606"
+            + "0585712688028315849324172582722748448938768134500098005690";
+        String y = 
"297320154107898594969162703371411878757449109919929193169657424280609259087338914952452468191452153"
+            + "1633519626430088785609447337443826933969196755052278553401";
+
+        KeyFactory keyFactory = KeyFactory.getInstance("EC");
+        AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC");
+        parameters.init(new ECGenParameterSpec("secp521r1"));
+        ECParameterSpec ecParameters = 
parameters.getParameterSpec(ECParameterSpec.class);
+        ECPoint pubPoint = new ECPoint(new BigInteger(x), new BigInteger(y));
+        KeySpec keySpec = new ECPublicKeySpec(pubPoint, ecParameters);
+        PublicKey publicKey = keyFactory.generatePublic(keySpec);
+
+        assertTrue(PublickeyLoginModule.equals(publicKey, storedKey));
+
+        // Make sure a different stored key does not work
+        String differentKey = 
"AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBL4+Vytknywh/XuOluxIqcHRoBsZHa12z+jpK"
+            + "pwuGFlzlq3yatwC8DqUaywJjzSnoGKSge9GBjuFYwvHN17hq8U=";
+        assertFalse(PublickeyLoginModule.equals(publicKey, differentKey));
+    }
+
+    @Test
+    public void testEC256() throws FailedLoginException, 
NoSuchAlgorithmException, InvalidKeySpecException, 
InvalidParameterSpecException {
+        // ecdsa-sha2-nistp256 - generated using: ssh-keygen -t ecdsa
+        String storedKey = 
"AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBL4+Vytknywh/XuOluxIqcHRoBsZHa12z+jpK"
+            + "pwuGFlzlq3yatwC8DqUaywJjzSnoGKSge9GBjuFYwvHN17hq8U=";
+        String x = 
"-29742501866672735446035294501787338870744851402037490785638836399245997090445";
+        String y = 
"-47637824304079393691947094099226900728731860400898598466261954347951527449659";
+
+        KeyFactory keyFactory = KeyFactory.getInstance("EC");
+        AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC");
+        parameters.init(new ECGenParameterSpec("secp256r1"));
+        ECParameterSpec ecParameters = 
parameters.getParameterSpec(ECParameterSpec.class);
+        ECPoint pubPoint = new ECPoint(new BigInteger(x), new BigInteger(y));
+        KeySpec keySpec = new ECPublicKeySpec(pubPoint, ecParameters);
+        PublicKey publicKey = keyFactory.generatePublic(keySpec);
+
+        assertTrue(PublickeyLoginModule.equals(publicKey, storedKey));
+
+        // Make sure a different stored key does not work
+        String differentKey = 
"AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBDWwVudH/QYr/Nlkf/lZ0yMXVL+PvXBsGat8"
+            + "+n07/Bw0xZGP5E8+x1wbkZVS6qx8XyPMI61NnCRLawB+UX3ZE/A=";
+        assertFalse(PublickeyLoginModule.equals(publicKey, differentKey));
+    }
+
+    @Test
+    public void testEC256_2() throws FailedLoginException, 
NoSuchAlgorithmException, InvalidKeySpecException, 
InvalidParameterSpecException {
+        // ecdsa-sha2-nistp256 - generated using: ssh-keygen -t ecdsa
+        String storedKey = 
"AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBDWwVudH/QYr/Nlkf/lZ0yMXVL+PvXBsGat8"
+            + "+n07/Bw0xZGP5E8+x1wbkZVS6qx8XyPMI61NnCRLawB+UX3ZE/A=";
+        String x = 
"24284145843828879115537963613603143837878136357229118319568173718380870376500";
+        String y = 
"-26429272137078923303974425138822683171929812869671300956629169158527526562832";
+
+        KeyFactory keyFactory = KeyFactory.getInstance("EC");
+        AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC");
+        parameters.init(new ECGenParameterSpec("secp256r1"));
+        ECParameterSpec ecParameters = 
parameters.getParameterSpec(ECParameterSpec.class);
+        ECPoint pubPoint = new ECPoint(new BigInteger(x), new BigInteger(y));
+        KeySpec keySpec = new ECPublicKeySpec(pubPoint, ecParameters);
+        PublicKey publicKey = keyFactory.generatePublic(keySpec);
+
+        assertTrue(PublickeyLoginModule.equals(publicKey, storedKey));
+
+        // Make sure a different stored key does not work
+        String differentKey = 
"AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBL4+Vytknywh/XuOluxIqcHRoBsZHa12z+jpK"
+            + "pwuGFlzlq3yatwC8DqUaywJjzSnoGKSge9GBjuFYwvHN17hq8U=";
+        assertFalse(PublickeyLoginModule.equals(publicKey, differentKey));
+    }
+
+}
diff --git 
a/jaas/modules/src/test/java/org/apache/karaf/jaas/modules/publickey/PublicKeyLoginModuleTest.java
 
b/jaas/modules/src/test/java/org/apache/karaf/jaas/modules/publickey/PublicKeyLoginModuleTest.java
new file mode 100644
index 0000000..a0caf13
--- /dev/null
+++ 
b/jaas/modules/src/test/java/org/apache/karaf/jaas/modules/publickey/PublicKeyLoginModuleTest.java
@@ -0,0 +1,287 @@
+/*
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *  under the License.
+ */
+package org.apache.karaf.jaas.modules.publickey;
+
+import static org.apache.karaf.jaas.modules.PrincipalHelper.names;
+import static org.hamcrest.Matchers.isIn;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.AlgorithmParameters;
+import java.security.KeyFactory;
+import java.security.PublicKey;
+import java.security.spec.DSAPublicKeySpec;
+import java.security.spec.ECGenParameterSpec;
+import java.security.spec.ECParameterSpec;
+import java.security.spec.ECPoint;
+import java.security.spec.ECPublicKeySpec;
+import java.security.spec.KeySpec;
+import java.security.spec.RSAPublicKeySpec;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.FailedLoginException;
+
+import org.apache.felix.utils.properties.Properties;
+import org.apache.karaf.jaas.boot.principal.RolePrincipal;
+import org.apache.karaf.jaas.boot.principal.UserPrincipal;
+import org.apache.karaf.jaas.modules.NamePubkeyCallbackHandler;
+import org.junit.Test;
+
+public class PublicKeyLoginModuleTest {
+
+    private static final String PK_PROPERTIES_FILE = 
"org/apache/karaf/jaas/modules/publickey/pubkey.properties";
+
+    @Test
+    public void testRSALogin() throws Exception {
+        Properties options = getLoginModuleOptions();
+        PublickeyLoginModule module = new PublickeyLoginModule();
+        Subject subject = new Subject();
+
+        String knownModulus = 
"2504227846033126752625313329217708474924890377669312098933267135871562327792150810915433595733"
+            + 
"979130785790337621243914845149325143098632580183245971502051291613503136182182218708721890923769091345704"
+            + 
"119963221758691543226829294312457492456071842409242817598014777158790065648435489978774648853589909638928"
+            + 
"448069481622573966178879417253888452317622624006445863588961367514293886664167742695648199055900918338245"
+            + 
"701727653606086096756173044470526840851957391900922886984556493506186438991284463663361749451775578708454"
+            + 
"0181594148839238901052763862484299588887844606103377160953183624788815045644521767391398467190125279747";
+
+        // Generate a PublicKey using the known values
+        BigInteger modulus = new BigInteger(knownModulus);
+        BigInteger exponent = new BigInteger("65537");
+        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+        KeySpec publicKeySpec = new RSAPublicKeySpec(modulus, exponent);
+        PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
+
+        module.initialize(subject, new NamePubkeyCallbackHandler("rsa", 
publicKey), null, options);
+
+        assertEquals("Precondition", 0, subject.getPrincipals().size());
+        assertTrue(module.login());
+        assertTrue(module.commit());
+
+        assertFalse(subject.getPrincipals().isEmpty());
+        assertThat("rsa", 
isIn(names(subject.getPrincipals(UserPrincipal.class))));
+        assertThat("ssh", 
isIn(names(subject.getPrincipals(RolePrincipal.class))));
+
+        assertTrue(module.logout());
+        assertEquals("Principals should be gone as the user has logged out", 
0, subject.getPrincipals().size());
+    }
+
+    @Test
+    public void testDSALogin() throws Exception {
+        Properties options = getLoginModuleOptions();
+        PublickeyLoginModule module = new PublickeyLoginModule();
+        Subject subject = new Subject();
+
+        String p = 
"1076175237625726563105954460741409330556298182412863930703571469202992312952487088821612089126846931217220"
+            + 
"139938550642040962241586994856559462488140821681403960733982209827487135132210000913512532065787125116985685638"
+            + 
"40437219296134522589816052156357553531846010339651017908589163855315552516201352809575855397";
+        String q = "918380515194943729419256231914804453973955269349";
+        String g = 
"5928865413019314795162062081939159959737363875586187627523617102819491716184351195073908492559564825805562"
+            + 
"104476892066919492044841627907376461274343797017375757242038772707578284292374846844427026690399002493750530347"
+            + 
"2378225083646830569532678306021077676137269211638266431262139218141967811197461432032698462";
+        String y = 
"3780682190459260799543888842390974417268312111951424991203659597814001671832656608276823896973755971735795"
+            + 
"130565245682634187551545737028902938478313465290457154458005480679650487421678748598551351730312164280338152996"
+            + 
"0448119336850459047721615478019482431582683540283279032651976075781966545889409150149549269";
+
+        // Generate a PublicKey using the known values
+        KeyFactory keyFactory = KeyFactory.getInstance("DSA");
+        KeySpec publicKeySpec = new DSAPublicKeySpec(new BigInteger(y), new 
BigInteger(p), new BigInteger(q), new BigInteger(g));
+        PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
+
+        module.initialize(subject, new NamePubkeyCallbackHandler("dsa", 
publicKey), null, options);
+
+        assertEquals("Precondition", 0, subject.getPrincipals().size());
+        assertTrue(module.login());
+        assertTrue(module.commit());
+
+        assertFalse(subject.getPrincipals().isEmpty());
+        assertThat("dsa", 
isIn(names(subject.getPrincipals(UserPrincipal.class))));
+        // We didn't configure any roles
+        
assertTrue(names(subject.getPrincipals(RolePrincipal.class)).isEmpty());
+
+        assertTrue(module.logout());
+        assertEquals("Principals should be gone as the user has logged out", 
0, subject.getPrincipals().size());
+    }
+
+    @Test
+    public void testECLogin() throws Exception {
+        Properties options = getLoginModuleOptions();
+        PublickeyLoginModule module = new PublickeyLoginModule();
+        Subject subject = new Subject();
+
+        String x = 
"-29742501866672735446035294501787338870744851402037490785638836399245997090445";
+        String y = 
"-47637824304079393691947094099226900728731860400898598466261954347951527449659";
+
+        KeyFactory keyFactory = KeyFactory.getInstance("EC");
+        AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC");
+        parameters.init(new ECGenParameterSpec("secp256r1"));
+        ECParameterSpec ecParameters = 
parameters.getParameterSpec(ECParameterSpec.class);
+        ECPoint pubPoint = new ECPoint(new BigInteger(x), new BigInteger(y));
+        KeySpec keySpec = new ECPublicKeySpec(pubPoint, ecParameters);
+        PublicKey publicKey = keyFactory.generatePublic(keySpec);
+
+        module.initialize(subject, new NamePubkeyCallbackHandler("ec", 
publicKey), null, options);
+
+        assertEquals("Precondition", 0, subject.getPrincipals().size());
+        assertTrue(module.login());
+        assertTrue(module.commit());
+
+        assertFalse(subject.getPrincipals().isEmpty());
+        assertThat("ec", 
isIn(names(subject.getPrincipals(UserPrincipal.class))));
+        assertThat("ssh", 
isIn(names(subject.getPrincipals(RolePrincipal.class))));
+
+        assertTrue(module.logout());
+        assertEquals("Principals should be gone as the user has logged out", 
0, subject.getPrincipals().size());
+    }
+
+    @Test
+    public void testUnknownUser() throws Exception {
+        Properties options = getLoginModuleOptions();
+        PublickeyLoginModule module = new PublickeyLoginModule();
+        Subject subject = new Subject();
+
+        String knownModulus = 
"2504227846033126752625313329217708474924890377669312098933267135871562327792150810915433595733"
+            + 
"979130785790337621243914845149325143098632580183245971502051291613503136182182218708721890923769091345704"
+            + 
"119963221758691543226829294312457492456071842409242817598014777158790065648435489978774648853589909638928"
+            + 
"448069481622573966178879417253888452317622624006445863588961367514293886664167742695648199055900918338245"
+            + 
"701727653606086096756173044470526840851957391900922886984556493506186438991284463663361749451775578708454"
+            + 
"0181594148839238901052763862484299588887844606103377160953183624788815045644521767391398467190125279747";
+
+        // Generate a PublicKey using the known values
+        BigInteger modulus = new BigInteger(knownModulus);
+        BigInteger exponent = new BigInteger("65537");
+        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+        KeySpec publicKeySpec = new RSAPublicKeySpec(modulus, exponent);
+        PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
+
+        module.initialize(subject, new NamePubkeyCallbackHandler("unknown", 
publicKey), null, options);
+
+        assertEquals("Precondition", 0, subject.getPrincipals().size());
+        try {
+            module.login();
+            fail("Failure expected on an unknown user");
+        } catch (FailedLoginException ex) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testUnknownKeyRSA() throws Exception {
+        Properties options = getLoginModuleOptions();
+        PublickeyLoginModule module = new PublickeyLoginModule();
+        Subject subject = new Subject();
+
+        String knownModulus = 
"2504227846033126752625313329217708474924890377669312098933267135871562327792150810915433595733"
+            + 
"979130785790337621243914845149325143098632580183245971502051291613503136182182218708721890923769091345704"
+            + 
"119963221758691543226829294312457492456071842409242817598014777158790065648435489978774648853589909638928"
+            + 
"448069481622573966178879417253888452317622624006445863588961367514293886664167742695648199055900918338245"
+            + 
"701727653606086096756173044470526840851957391900922886984556493506186438991284463663361749451775578708454"
+            + 
"0181594148839238901052763862484299588887844606103377160953183624788815045644521767391398467190125279745";
+
+        // Generate a PublicKey using the known values
+        BigInteger modulus = new BigInteger(knownModulus);
+        BigInteger exponent = new BigInteger("65537");
+        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+        KeySpec publicKeySpec = new RSAPublicKeySpec(modulus, exponent);
+        PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
+
+        module.initialize(subject, new NamePubkeyCallbackHandler("rsa", 
publicKey), null, options);
+
+        assertEquals("Precondition", 0, subject.getPrincipals().size());
+        try {
+            module.login();
+            fail("Failure expected on an unknown user");
+        } catch (FailedLoginException ex) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testUnknownKeyDSA() throws Exception {
+        Properties options = getLoginModuleOptions();
+        PublickeyLoginModule module = new PublickeyLoginModule();
+        Subject subject = new Subject();
+
+        String p = 
"1076175237625726563105954460741409330556298182412863930703571469202992312952487088821612089126846931217220"
+            + 
"139938550642040962241586994856559462488140821681403960733982209827487135132210000913512532065787125116985685638"
+            + 
"40437219296134522589816052156357553531846010339651017908589163855315552516201352809575855397";
+        String q = "918380515194943729419256231914804453973955269349";
+        String g = 
"5928865413019314795162062081939159959737363875586187627523617102819491716184351195073908492559564825805562"
+            + 
"104476892066919492044841627907376461274343797017375757242038772707578284292374846844427026690399002493750530347"
+            + 
"2378225083646830569532678306021077676137269211638266431262139218141967811197461432032698462";
+        String y = 
"3780682190459260799543888842390974417268312111951424991203659597814001671832656608276823896973755971735795"
+            + 
"130565245682634187551545737028902938478313465290457154458005480679650487421678748598551351730312164280338152996"
+            + 
"0448119336850459047721615478019482431582683540283279032651976075781966545889409150149549267";
+
+        // Generate a PublicKey using the known values
+        KeyFactory keyFactory = KeyFactory.getInstance("DSA");
+        KeySpec publicKeySpec = new DSAPublicKeySpec(new BigInteger(y), new 
BigInteger(p), new BigInteger(q), new BigInteger(g));
+        PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
+
+        module.initialize(subject, new NamePubkeyCallbackHandler("dsa", 
publicKey), null, options);
+
+        assertEquals("Precondition", 0, subject.getPrincipals().size());
+        try {
+            module.login();
+            fail("Failure expected on an unknown user");
+        } catch (FailedLoginException ex) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testUnknownKeyEC() throws Exception {
+        Properties options = getLoginModuleOptions();
+        PublickeyLoginModule module = new PublickeyLoginModule();
+        Subject subject = new Subject();
+
+        String x = 
"2145382594999641569030545431803328907795332312211583318014254232969998637145";
+        String y = 
"52282205184471090919696434245736603165041352971927370430120381994413951213993";
+
+        KeyFactory keyFactory = KeyFactory.getInstance("EC");
+        AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC");
+        parameters.init(new ECGenParameterSpec("secp256r1"));
+        ECParameterSpec ecParameters = 
parameters.getParameterSpec(ECParameterSpec.class);
+        ECPoint pubPoint = new ECPoint(new BigInteger(x), new BigInteger(y));
+        KeySpec keySpec = new ECPublicKeySpec(pubPoint, ecParameters);
+        PublicKey publicKey = keyFactory.generatePublic(keySpec);
+
+        module.initialize(subject, new NamePubkeyCallbackHandler("ec", 
publicKey), null, options);
+
+        assertEquals("Precondition", 0, subject.getPrincipals().size());
+        try {
+            module.login();
+            fail("Failure expected on an unknown user");
+        } catch (FailedLoginException ex) {
+            // expected
+        }
+    }
+
+
+    protected Properties getLoginModuleOptions() throws IOException {
+        String basedir = System.getProperty("basedir");
+        if (basedir == null) {
+            basedir = new File(".").getCanonicalPath();
+        }
+        File file = new File(basedir + "/target/test-classes/" + 
PK_PROPERTIES_FILE);
+        return new Properties(file);
+    }
+
+}
diff --git 
a/jaas/modules/src/test/resources/org/apache/karaf/jaas/modules/publickey/pubkey.properties
 
b/jaas/modules/src/test/resources/org/apache/karaf/jaas/modules/publickey/pubkey.properties
new file mode 100644
index 0000000..40a7b62
--- /dev/null
+++ 
b/jaas/modules/src/test/resources/org/apache/karaf/jaas/modules/publickey/pubkey.properties
@@ -0,0 +1,20 @@
+################################################################################
+#
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You under the Apache License, Version 2.0
+#    (the "License"); you may not use this file except in compliance with
+#    the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+################################################################################
+
+users=./target/test-classes/org/apache/karaf/jaas/modules/publickey/pubkey.users
diff --git 
a/jaas/modules/src/test/resources/org/apache/karaf/jaas/modules/publickey/pubkey.users
 
b/jaas/modules/src/test/resources/org/apache/karaf/jaas/modules/publickey/pubkey.users
new file mode 100644
index 0000000..3ea58e4
--- /dev/null
+++ 
b/jaas/modules/src/test/resources/org/apache/karaf/jaas/modules/publickey/pubkey.users
@@ -0,0 +1,23 @@
+################################################################################
+#
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You under the Apache License, Version 2.0
+#    (the "License"); you may not use this file except in compliance with
+#    the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+################################################################################
+
+rsa=AAAAB3NzaC1yc2EAAAADAQABAAABAQDGX4CpCL49sWHaIuDE4VbGkdTMhsDLV3b8MDZ37Llsx3kRBs/x7G3OhSvQPhIjMNcbnUnCr+6O6poKjRcFI1Aj76TiSSYlvz9QbsWqc50ZwCuR39h6F9u8f9k62AV7IVA4aNVSJBFn2nOA00HOWvDDrU3ykG0cPeJcmP1lPeOO9WJVG7dc37v3soZZniIH+uop/UFQ4Ga0zWy4xjggAy2rE2p0BYHchrJb43ovInh5cGgXx2vNVwURsAf0TAPJwn7GLNpMYr3IFbRC3Tbe1wPdy9YM4rFlKL78o/dFbvUOH+Vd1BlYDofoxT4kHxod7W5wPALBr/Bm8CD2tR6OLLoD,_g_:admingroup
+dsa=AAAAB3NzaC1kc3MAAACBAJlAn/bPWpugKCLyoQpe8AbSZiIxdEJhl+VV8YEH6jfb9lLPA9JkQAf/lnG1Jx01UM65RRyKtnMAiBpkhrPy3DbqJ4FgYBmc1Sdiufomilq6zSbE0esJEMyxEvSNDQLqIiUcSwVyJJj1vpV6ZPA6ihipTIaiSV+rmfKcS05i27UlAAAAFQCg3ZtIytPmGILQ7OEifIJvCSlS5QAAAIBUbgpjk7vSWVNICgKG6OrXeK0kJYRG6AaUZSiB2neoABMyGIHQ8dBCk+jtYqRMYyoc+OPi5q43VcDMxgzR/cHGjZi60w/I3M83072dAdaoi0cleL/V8NaH+SOvkkYkAG57OIa3ly9PVpPfeXRnbbjkz1EsrvXIelqb5enLhlIgXgAAAIA11rUkN/J3K7nw/BiolhpZR3MVhWWIJFjJyU7ZC0yO8a+3AExuhTI6YQvsyvlY69KCwAwZsZvx9DryDE5x
 [...]
+ec=AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBL4+Vytknywh/XuOluxIqcHRoBsZHa12z+jpKpwuGFlzlq3yatwC8DqUaywJjzSnoGKSge9GBjuFYwvHN17hq8U=,_g_:admingroup
+_g_\:admingroup = group,admin,manager,viewer,systembundles,ssh

Reply via email to