/// <summary>
        /// Return a new Signature object based on the signature algorithm of the
        /// public key with keyName (derived from certificateName).
        /// </summary>
        ///
        /// <param name="certificateName">The certificate name.</param>
        /// <param name="digestAlgorithm"></param>
        /// <returns>A new object of the correct subclass of Signature.</returns>
        private Signature makeSignatureByCertificate(Name certificateName,
				DigestAlgorithm[] digestAlgorithm)
        {
            Name keyName = net.named_data.jndn.security.certificate.IdentityCertificate
                    .certificateNameToPublicKeyName(certificateName);
            PublicKey publicKey = privateKeyStorage_.getPublicKey(keyName);
            KeyType keyType = publicKey.getKeyType();

            if (keyType == net.named_data.jndn.security.KeyType.RSA) {
                Sha256WithRsaSignature signature = new Sha256WithRsaSignature();
                digestAlgorithm[0] = net.named_data.jndn.security.DigestAlgorithm.SHA256;

                signature.getKeyLocator().setType(net.named_data.jndn.KeyLocatorType.KEYNAME);
                signature.getKeyLocator().setKeyName(certificateName.getPrefix(-1));

                return signature;
            } else if (keyType == net.named_data.jndn.security.KeyType.ECDSA) {
                Sha256WithEcdsaSignature signature_0 = new Sha256WithEcdsaSignature();
                digestAlgorithm[0] = net.named_data.jndn.security.DigestAlgorithm.SHA256;

                signature_0.getKeyLocator().setType(net.named_data.jndn.KeyLocatorType.KEYNAME);
                signature_0.getKeyLocator().setKeyName(certificateName.getPrefix(-1));

                return signature_0;
            } else
                throw new SecurityException("Key type is not recognized");
        }
        /// <summary>
        /// Prepare an unsigned identity certificate.
        /// </summary>
        ///
        /// <param name="keyName">The key name, e.g., `/{identity_name}/ksk-123456`.</param>
        /// <param name="publicKey">The public key to sign.</param>
        /// <param name="signingIdentity">The signing identity.</param>
        /// <param name="notBefore">See IdentityCertificate.</param>
        /// <param name="notAfter">See IdentityCertificate.</param>
        /// <param name="subjectDescription">on the keyName.</param>
        /// <param name="certPrefix">signingIdentity and the subject identity. If the signingIdentity is a prefix of the subject identity, `KEY` will be inserted after the signingIdentity, otherwise `KEY` is inserted after subject identity (i.e., before `ksk-...`).</param>
        /// <returns>The unsigned IdentityCertificate, or null if the inputs are invalid.</returns>
        public IdentityCertificate prepareUnsignedIdentityCertificate(
				Name keyName, PublicKey publicKey, Name signingIdentity,
				double notBefore, double notAfter, IList subjectDescription,
				Name certPrefix)
        {
            if (keyName.size() < 1)
                return null;

            String tempKeyIdPrefix = keyName.get(-1).toEscapedString();
            if (tempKeyIdPrefix.Length < 4)
                return null;
            String keyIdPrefix = tempKeyIdPrefix.Substring(0,(4)-(0));
            if (!keyIdPrefix.equals("ksk-") && !keyIdPrefix.equals("dsk-"))
                return null;

            IdentityCertificate certificate = new IdentityCertificate();
            Name certName = new Name();

            if (certPrefix == null) {
                // No certificate prefix hint, so infer the prefix.
                if (signingIdentity.match(keyName))
                    certName.append(signingIdentity).append("KEY")
                            .append(keyName.getSubName(signingIdentity.size()))
                            .append("ID-CERT")
                            .appendVersion((long) net.named_data.jndn.util.Common.getNowMilliseconds());
                else
                    certName.append(keyName.getPrefix(-1)).append("KEY")
                            .append(keyName.get(-1)).append("ID-CERT")
                            .appendVersion((long) net.named_data.jndn.util.Common.getNowMilliseconds());
            } else {
                // A cert prefix hint is supplied, so determine the cert name.
                if (certPrefix.match(keyName) && !certPrefix.equals(keyName))
                    certName.append(certPrefix).append("KEY")
                            .append(keyName.getSubName(certPrefix.size()))
                            .append("ID-CERT")
                            .appendVersion((long) net.named_data.jndn.util.Common.getNowMilliseconds());
                else
                    return null;
            }

            certificate.setName(certName);
            certificate.setNotBefore(notBefore);
            certificate.setNotAfter(notAfter);
            certificate.setPublicKeyInfo(publicKey);

            if (subjectDescription == null || (subjectDescription.Count==0))
                certificate
                        .addSubjectDescription(new CertificateSubjectDescription(
                                "2.5.4.41", keyName.getPrefix(-1).toUri()));
            else {
                for (int i = 0; i < subjectDescription.Count; ++i)
                    certificate
                            .addSubjectDescription((CertificateSubjectDescription) subjectDescription[i]);
            }

            try {
                certificate.encode();
            } catch (DerEncodingException ex) {
                throw new SecurityException("DerEncodingException: " + ex);
            } catch (DerDecodingException ex_0) {
                throw new SecurityException("DerDecodingException: " + ex_0);
            }

            return certificate;
        }
 private static Name certNameFromKeyName(Name keyName, int keyIdx)
 {
     if (keyIdx < 0)
         keyIdx = keyName.size() + keyIdx;
     return keyName.getPrefix(keyIdx).append("KEY")
             .append(keyName.getSubName(keyIdx)).append("ID-CERT")
             .append("0");
 }
        /// <summary>
        /// Throw an exception if it is an error for setDefaultKeyNameForIdentity to
        /// set it.
        /// </summary>
        ///
        /// <param name="keyName">The key name.</param>
        /// <param name="identityNameCheck">The identity name to check the keyName.</param>
        /// <exception cref="System.Security.SecurityException">if the identity name does not match the key nameor other problem.</exception>
        protected internal void checkSetDefaultKeyNameForIdentity(Name keyName,
				Name identityNameCheck)
        {
            Name identityName = keyName.getPrefix(-1);

            if (identityNameCheck.size() > 0
                    && !identityNameCheck.equals(identityName))
                throw new SecurityException(
                        "The specified identity name does not match the key name");
        }
        public void testPrefix()
        {
            Name name = new Name("/edu/cmu/andrew/user/3498478");
            Name prefix1 = name.getPrefix(2);
            Assert.AssertEquals("Name prefix has " + prefix1.size()
                    + " components instead of 2", 2, prefix1.size());
            for (int i = 0; i < 2; ++i)
                Assert.AssertTrue(name.get(i).getValue().equals(prefix1.get(i).getValue()));

            Name prefix2 = name.getPrefix(100);
            Assert.AssertEquals(
                    "Prefix with more components than original should stop at end of original name",
                    name, prefix2);
        }
        /// <summary>
        /// Delete a public key and related certificates.
        /// </summary>
        ///
        /// <param name="keyName">The key name.</param>
        public override void deletePublicKeyInfo(Name keyName)
        {
            if (keyName.size() == 0)
                return;

            String keyId = keyName.get(-1).toEscapedString();
            Name identityName = keyName.getPrefix(-1);

            try {
                PreparedStatement statement = database_
                        .prepareStatement("DELETE FROM Certificate WHERE "
                                + net.named_data.jndn.security.identity.Sqlite3IdentityStorageBase.WHERE_deletePublicKeyInfo);
                statement.setString(1, identityName.toUri());
                statement.setString(2, keyId);

                try {
                    statement.executeUpdate();
                } finally {
                    statement.close();
                }

                statement = database_.prepareStatement("DELETE FROM Key WHERE "
                        + net.named_data.jndn.security.identity.Sqlite3IdentityStorageBase.WHERE_deletePublicKeyInfo);
                statement.setString(1, identityName.toUri());
                statement.setString(2, keyId);

                try {
                    statement.executeUpdate();
                } finally {
                    statement.close();
                }
            } catch (SQLException exception) {
                throw new SecurityException("BasicIdentityStorage: SQLite error: "
                        + exception);
            }
        }
        /// <summary>
        /// In table Key, set 'active' to isActive for the keyName.
        /// </summary>
        ///
        /// <param name="keyName">The name of the key.</param>
        /// <param name="isActive">The value for the 'active' field.</param>
        protected internal override void updateKeyStatus(Name keyName, bool isActive)
        {
            String keyId = keyName.get(-1).toEscapedString();
            Name identityName = keyName.getPrefix(-1);

            try {
                PreparedStatement statement = database_
                        .prepareStatement("UPDATE Key SET active=? WHERE "
                                + net.named_data.jndn.security.identity.Sqlite3IdentityStorageBase.WHERE_updateKeyStatus);
                statement.setInt(1, ((isActive) ? 1 : 0));
                statement.setString(2, identityName.toUri());
                statement.setString(3, keyId);

                try {
                    statement.executeUpdate();
                } finally {
                    statement.close();
                }
            } catch (SQLException exception) {
                throw new SecurityException("BasicIdentityStorage: SQLite error: "
                        + exception);
            }
        }
        public void testAutoCreateIdentity()
        {
            Name keyName1 = new Name(
                    "/TestSqlIdentityStorage/KeyType/RSA/ksk-12345");
            Name identityName = keyName1.getPrefix(-1);

            byte[] decodedKey = net.named_data.jndn.util.Common.base64Decode(RSA_DER);
            identityStorage.addKey(keyName1, net.named_data.jndn.security.KeyType.RSA, new Blob(decodedKey,
                    false));
            identityStorage.setDefaultKeyNameForIdentity(keyName1);

            AssertTrue("Key was not added", identityStorage.doesKeyExist(keyName1));
            AssertTrue("Identity for key was not automatically created",
                    identityStorage.doesIdentityExist(identityName));

            AssertTrue("Default key was not set on identity creation",
                    identityManager.getDefaultKeyNameForIdentity(identityName)
                            .equals(keyName1));

            try {
                identityStorage.getDefaultCertificateNameForKey(keyName1);
                Fail();
            } catch (SecurityException ex) {
            }

            // We have no private key for signing.
            try {
                identityManager.selfSign(keyName1);
                Fail();
            } catch (SecurityException ex_0) {
            }

            try {
                identityStorage.getDefaultCertificateNameForKey(keyName1);
                Fail();
            } catch (SecurityException ex_1) {
            }

            try {
                identityManager.getDefaultCertificateNameForIdentity(identityName);
                Fail();
            } catch (SecurityException ex_2) {
            }

            Name keyName2 = identityManager
                    .generateRSAKeyPairAsDefault(identityName);
            IdentityCertificate cert = identityManager.selfSign(keyName2);
            identityManager.addCertificateAsIdentityDefault(cert);

            Name certName1 = identityManager
                    .getDefaultCertificateNameForIdentity(identityName);
            Name certName2 = identityStorage
                    .getDefaultCertificateNameForKey(keyName2);

            AssertTrue(
                    "Key-certificate mapping and identity-certificate mapping are not consistent",
                    certName1.equals(certName2));

            keyChain.deleteIdentity(identityName);
            AssertFalse(identityStorage.doesKeyExist(keyName1));
        }
        /// <summary>
        /// Get the public key DER blob from the identity storage.
        /// </summary>
        ///
        /// <param name="keyName">The name of the requested public key.</param>
        /// <returns>The DER Blob.</returns>
        /// <exception cref="System.Security.SecurityException">if the key doesn't exist.</exception>
        public override sealed Blob getKey(Name keyName)
        {
            if (keyName.size() == 0)
                throw new SecurityException(
                        "BasicIdentityStorage::getKey: Empty keyName");

            String keyId = keyName.get(-1).toEscapedString();
            Name identityName = keyName.getPrefix(-1);

            try {
                PreparedStatement statement = database_
                        .prepareStatement(net.named_data.jndn.security.identity.Sqlite3IdentityStorageBase.SELECT_getKey);
                statement.setString(1, identityName.toUri());
                statement.setString(2, keyId);

                try {
                    SqlDataReader result = statement.executeQuery();

                    if (result.NextResult())
                        return new Blob(result.getBytes("public_key"), false);
                    else
                        throw new SecurityException(
                                "BasicIdentityStorage::getKey: The key does not exist");
                } finally {
                    statement.close();
                }
            } catch (SQLException exception) {
                throw new SecurityException("BasicIdentityStorage: SQLite error: "
                        + exception);
            }
        }
        /// <summary>
        /// Set a key as the default key of an identity. The identity name is inferred
        /// from keyName.
        /// </summary>
        ///
        /// <param name="keyName">The name of the key.</param>
        /// <param name="identityNameCheck"></param>
        public override sealed void setDefaultKeyNameForIdentity(Name keyName,
				Name identityNameCheck)
        {
            checkSetDefaultKeyNameForIdentity(keyName, identityNameCheck);

            String keyId = keyName.get(-1).toEscapedString();
            Name identityName = keyName.getPrefix(-1);

            try {
                // Reset the previous default Key.
                PreparedStatement statement = database_
                        .prepareStatement("UPDATE Key SET default_key=0 WHERE "
                                + net.named_data.jndn.security.identity.Sqlite3IdentityStorageBase.WHERE_setDefaultKeyNameForIdentity_reset);
                statement.setString(1, identityName.toUri());
                try {
                    statement.executeUpdate();
                } finally {
                    statement.close();
                }

                // Set the current default Key.
                statement = database_
                        .prepareStatement("UPDATE Key SET default_key=1 WHERE "
                                + net.named_data.jndn.security.identity.Sqlite3IdentityStorageBase.WHERE_setDefaultKeyNameForIdentity_set);
                statement.setString(1, identityName.toUri());
                statement.setString(2, keyId);
                try {
                    statement.executeUpdate();
                } finally {
                    statement.close();
                }
            } catch (SQLException exception) {
                throw new SecurityException("BasicIdentityStorage: SQLite error: "
                        + exception);
            }
        }
        /// <summary>
        /// Get the default certificate name for the specified key.
        /// </summary>
        ///
        /// <param name="keyName">The key name.</param>
        /// <returns>The default certificate name.</returns>
        /// <exception cref="System.Security.SecurityException">if the default certificate name for the key nameis not set.</exception>
        public override sealed Name getDefaultCertificateNameForKey(Name keyName)
        {
            String keyId = keyName.get(-1).toEscapedString();
            Name identityName = keyName.getPrefix(-1);

            try {
                PreparedStatement statement = database_
                        .prepareStatement(net.named_data.jndn.security.identity.Sqlite3IdentityStorageBase.SELECT_getDefaultCertificateNameForKey);
                statement.setString(1, identityName.toUri());
                statement.setString(2, keyId);

                try {
                    SqlDataReader result = statement.executeQuery();

                    if (result.NextResult())
                        return new Name((string)result["cert_name"]);
                    else
                        throw new SecurityException(
                                "BasicIdentityStorage.getDefaultCertificateNameForKey: The default certificate for the key name is not defined");
                } finally {
                    statement.close();
                }
            } catch (SQLException exception) {
                throw new SecurityException("BasicIdentityStorage: SQLite error: "
                        + exception);
            }
        }
        /// <summary>
        /// Append all the certificate names of a particular key name to the nameList.
        /// </summary>
        ///
        /// <param name="keyName">The key name to search for.</param>
        /// <param name="nameList">Append result names to nameList.</param>
        /// <param name="isDefault"></param>
        public override void getAllCertificateNamesOfKey(Name keyName, ArrayList nameList,
				bool isDefault)
        {
            try {
                String sql = (isDefault) ? net.named_data.jndn.security.identity.Sqlite3IdentityStorageBase.SELECT_getAllCertificateNamesOfKey_default_true
                        : net.named_data.jndn.security.identity.Sqlite3IdentityStorageBase.SELECT_getAllCertificateNamesOfKey_default_false;
                PreparedStatement statement = database_.prepareStatement(sql);
                statement.setString(1, keyName.getPrefix(-1).toUri());
                statement.setString(2, keyName.get(-1).toEscapedString());

                try {
                    SqlDataReader result = statement.executeQuery();

                    while (result.NextResult())
                        ILOG.J2CsMapping.Collections.Collections.Add(nameList,new Name((string)result["cert_name"]));
                } finally {
                    statement.close();
                }
            } catch (SQLException exception) {
                throw new SecurityException("BasicIdentityStorage: SQLite error: "
                        + exception);
            }
        }
        /// <summary>
        /// Check if the specified key already exists.
        /// </summary>
        ///
        /// <param name="keyName">The name of the key.</param>
        /// <returns>true if the key exists, otherwise false.</returns>
        public override sealed bool doesKeyExist(Name keyName)
        {
            String keyId = keyName.get(-1).toEscapedString();
            Name identityName = keyName.getPrefix(-1);

            try {
                PreparedStatement statement = database_
                        .prepareStatement(net.named_data.jndn.security.identity.Sqlite3IdentityStorageBase.SELECT_doesKeyExist);
                statement.setString(1, identityName.toUri());
                statement.setString(2, keyId);

                try {
                    SqlDataReader result = statement.executeQuery();

                    if (result.NextResult())
                        return result.getInt(1) > 0;
                    else
                        return false;
                } finally {
                    statement.close();
                }
            } catch (SQLException exception) {
                throw new SecurityException("BasicIdentityStorage: SQLite error: "
                        + exception);
            }
        }
Example #14
0
        /// <summary>
        /// Generate a self-signed certificate for a public key.
        /// </summary>
        ///
        /// <param name="keyName">The name of the public key.</param>
        /// <returns>The generated certificate.</returns>
        public IdentityCertificate selfSign(Name keyName)
        {
            IdentityCertificate certificate = new IdentityCertificate();

            Blob keyBlob = identityStorage_.getKey(keyName);
            PublicKey publicKey = new PublicKey(keyBlob);

            Calendar calendar = ILOG.J2CsMapping.Util.Calendar.getInstance();
            double notBefore = (double) calendar.getTimeInMillis();
            calendar.add(ILOG.J2CsMapping.Util.Calendar.YEAR, 2);
            double notAfter = (double) calendar.getTimeInMillis();

            certificate.setNotBefore(notBefore);
            certificate.setNotAfter(notAfter);

            Name certificateName = keyName.getPrefix(-1).append("KEY")
                    .append(keyName.get(-1)).append("ID-CERT")
                    .appendVersion((long) certificate.getNotBefore());
            certificate.setName(certificateName);

            certificate.setPublicKeyInfo(publicKey);
            certificate.addSubjectDescription(new CertificateSubjectDescription(
                    "2.5.4.41", keyName.toUri()));
            try {
                certificate.encode();
            } catch (DerEncodingException ex) {
                // We don't expect this to happen.
                ILOG.J2CsMapping.Util.Logging.Logger.getLogger(typeof(IdentityManager).FullName).log(ILOG.J2CsMapping.Util.Logging.Level.SEVERE,
                        null, ex);
                return null;
            } catch (DerDecodingException ex_0) {
                // We don't expect this to happen.
                ILOG.J2CsMapping.Util.Logging.Logger.getLogger(typeof(IdentityManager).FullName).log(ILOG.J2CsMapping.Util.Logging.Level.SEVERE,
                        null, ex_0);
                return null;
            }

            signByCertificate(certificate, certificate.getName());

            return certificate;
        }
Example #15
0
        private void construct(Name prefix, Name dataType)
        {
            Name fixedPrefix = new Name(prefix);
            Name fixedDataType = new Name(dataType);

            // Fill ekeyInfo_ with all permutations of dataType, including the 'E-KEY'
            // component of the name. This will be used in createContentKey to send
            // interests without reconstructing names every time.
            fixedPrefix.append(net.named_data.jndn.encrypt.algo.Encryptor.NAME_COMPONENT_READ);
            while (fixedDataType.size() > 0) {
                Name nodeName = new Name(fixedPrefix);
                nodeName.append(fixedDataType);
                nodeName.append(net.named_data.jndn.encrypt.algo.Encryptor.NAME_COMPONENT_E_KEY);

                ILOG.J2CsMapping.Collections.Collections.Put(eKeyInfo_,nodeName,new Producer.KeyInfo ());
                fixedDataType = fixedDataType.getPrefix(-1);
            }
            fixedPrefix.append(dataType);
            namespace_ = new Name(prefix);
            namespace_.append(net.named_data.jndn.encrypt.algo.Encryptor.NAME_COMPONENT_SAMPLE);
            namespace_.append(dataType);
        }
        /// <summary>
        /// Set a key as the default key of an identity. The identity name is inferred
        /// from keyName.
        /// </summary>
        ///
        /// <param name="keyName">The name of the key.</param>
        /// <param name="identityNameCheck"></param>
        public override void setDefaultKeyNameForIdentity(Name keyName,
				Name identityNameCheck)
        {
            Name identityName = keyName.getPrefix(-1);

            if (identityNameCheck.size() > 0
                    && !identityNameCheck.equals(identityName))
                throw new SecurityException(
                        "The specified identity name does not match the key name");

            String identity = identityName.toUri();
            if (identityStore_.Contains(identity)) {
                ((MemoryIdentityStorage.IdentityRecord ) ILOG.J2CsMapping.Collections.Collections.Get(identityStore_,identity))
                        .setDefaultKey(new Name(keyName));
            }
        }
        public void testPrepareUnsignedCertificate()
        {
            MemoryIdentityStorage identityStorage = new MemoryIdentityStorage();
            MemoryPrivateKeyStorage privateKeyStorage = new MemoryPrivateKeyStorage();
            IdentityManager identityManager = new IdentityManager(identityStorage,
                    privateKeyStorage);
            Name keyName = new Name("/test/ksk-1457560485494");
            identityStorage.addKey(keyName, net.named_data.jndn.security.KeyType.RSA,
                    new Blob(PUBLIC_KEY, false));

            ArrayList subjectDescriptions = new ArrayList();
            ILOG.J2CsMapping.Collections.Collections.Add(subjectDescriptions,new CertificateSubjectDescription(TEST_OID,
                            "TEST NAME"));
            IdentityCertificate newCertificate = identityManager
                    .prepareUnsignedIdentityCertificate(keyName,
                            keyName.getPrefix(1), toyCertNotBefore,
                            toyCertNotAfter, subjectDescriptions);

            // Update the generated certificate version to equal the one in toyCert.
            newCertificate.setName(new Name(newCertificate.getName().getPrefix(-1)
                    .append(toyCert.getName().get(-1))));

            // Make a copy to test encoding.
            IdentityCertificate certificateCopy = new IdentityCertificate(
                    newCertificate);
            Assert.AssertEquals(
                    "Prepared unsigned certificate dump does not have the expected format",
                    "" + toyCert, "" + certificateCopy);
        }
Example #18
0
        public void testMatch()
        {
            Name name = new Name("/edu/cmu/andrew/user/3498478");
            Name name2 = new Name(name);
            Assert.AssertTrue("Name does not match deep copy of itself", name.match(name2));

            name2 = name.getPrefix(2);
            Assert.AssertTrue("Name did not match prefix", name2.match(name));
            Assert.AssertFalse("Name should not match shorter name", name.match(name2));
            Assert.AssertTrue("Empty name should always match another",
                    new Name().match(name));
        }
Example #19
0
        private void fetchNextSegment(Interest originalInterest_0, Name dataName,
				long segment)
        {
            // Start with the original Interest to preserve any special selectors.
            Interest interest = new Interest(originalInterest_0);
            // Changing a field clears the nonce so that the library will generate a new one.
            interest.setChildSelector(0);
            interest.setMustBeFresh(false);
            interest.setName(dataName.getPrefix(-1).appendSegment(segment));
            try {
                face_.expressInterest(interest, this, this);
            } catch (IOException ex) {
                try {
                    onError_.onError(net.named_data.jndn.util.SegmentFetcher.ErrorCode.IO_ERROR,
                            "I/O error fetching the next segment " + ex);
                } catch (Exception exception) {
                    logger_.log(ILOG.J2CsMapping.Util.Logging.Level.SEVERE, "Error in onError", exception);
                }
            }
        }
        /// <summary>
        /// Add a new member with the given key named keyName into a schedule named
        /// scheduleName. The member's identity name is keyName.getPrefix(-1).
        /// </summary>
        ///
        /// <param name="scheduleName">The schedule name.</param>
        /// <param name="keyName">The name of the key.</param>
        /// <param name="key">A Blob of the public key DER.</param>
        /// <exception cref="GroupManagerDb.Error">If there's no schedule named scheduleName, ifthe member's identity name already exists, or other database error.</exception>
        public override void addMember(String scheduleName, Name keyName, Blob key)
        {
            int scheduleId = getScheduleId(scheduleName);
            if (scheduleId == -1)
                throw new GroupManagerDb.Error("The schedule does not exist");

            // Needs to be changed in the future.
            Name memberName = keyName.getPrefix(-1);

            try {
                PreparedStatement statement = database_
                        .prepareStatement(net.named_data.jndn.encrypt.Sqlite3GroupManagerDbBase.INSERT_addMember);
                statement.setInt(1, scheduleId);
                statement.setBytes(2, memberName.wireEncode(net.named_data.jndn.encoding.TlvWireFormat.get())
                        .getImmutableArray());
                statement.setBytes(3, keyName.wireEncode(net.named_data.jndn.encoding.TlvWireFormat.get())
                        .getImmutableArray());
                statement.setBytes(4, key.getImmutableArray());

                try {
                    statement.executeUpdate();
                } finally {
                    statement.close();
                }
            } catch (SQLException exception) {
                throw new GroupManagerDb.Error(
                        "Sqlite3GroupManagerDb.addMember: SQLite error: "
                                + exception);
            }
        }
        /// <summary>
        /// Add a public key to the identity storage. Also call addIdentity to ensure
        /// that the identityName for the key exists. However, if the key already
        /// exists, do nothing.
        /// </summary>
        ///
        /// <param name="keyName">The name of the public key to be added.</param>
        /// <param name="keyType">Type of the public key to be added.</param>
        /// <param name="publicKeyDer">A blob of the public key DER to be added.</param>
        public override sealed void addKey(Name keyName, KeyType keyType, Blob publicKeyDer)
        {
            if (keyName.size() == 0)
                return;

            if (doesKeyExist(keyName))
                return;

            String keyId = keyName.get(-1).toEscapedString();
            Name identityName = keyName.getPrefix(-1);

            addIdentity(identityName);

            try {
                PreparedStatement statement = database_
                        .prepareStatement("INSERT INTO Key (identity_name, key_identifier, key_type, public_key) values (?, ?, ?, ?)");
                statement.setString(1, identityName.toUri());
                statement.setString(2, keyId);
                statement.setInt(3, keyType.getNumericType());
                statement.setBytes(4, publicKeyDer.getImmutableArray());

                try {
                    statement.executeUpdate();
                } finally {
                    statement.close();
                }
            } catch (SQLException exception) {
                throw new SecurityException("BasicIdentityStorage: SQLite error: "
                        + exception);
            }
        }