/** * Delete a public key and related certificates. * * @param keyName The key name. */ public void deletePublicKeyInfo(Name keyName) throws SecurityException { 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 " + WHERE_deletePublicKeyInfo); statement.setString(1, identityName.toUri()); statement.setString(2, keyId); try { statement.executeUpdate(); } finally { statement.close(); } statement = database_.prepareStatement("DELETE FROM Key WHERE " + 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); } }
/** * Add a public key to the identity storage. Also call addIdentity to ensure that the identityName * for the key exists. * * @param keyName The name of the public key to be added. * @param keyType Type of the public key to be added. * @param publicKeyDer A blob of the public key DER to be added. * @throws SecurityException if a key with the keyName already exists. */ public final void addKey(Name keyName, KeyType keyType, Blob publicKeyDer) throws SecurityException { if (keyName.size() == 0) return; checkAddKey(keyName); 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); } }
/** * Set a key as the default key of an identity. The identity name is inferred from keyName. * * @param keyName The name of the key. * @param identityNameCheck The identity name to check that the keyName contains the same identity * name. If an empty name, it is ignored. */ public final void setDefaultKeyNameForIdentity(Name keyName, Name identityNameCheck) throws SecurityException { 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 " + 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 " + 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); } }
/** * Return a new Signature object based on the signature algorithm of the public key with keyName * (derived from certificateName). * * @param certificateName The certificate name. * @param digestAlgorithm Set digestAlgorithm[0] to the signature algorithm's digest algorithm, * e.g. DigestAlgorithm.SHA256. * @return A new object of the correct subclass of Signature. */ private Signature makeSignatureByCertificate( Name certificateName, DigestAlgorithm[] digestAlgorithm) throws SecurityException { Name keyName = IdentityCertificate.certificateNameToPublicKeyName(certificateName); PublicKey publicKey = privateKeyStorage_.getPublicKey(keyName); KeyType keyType = publicKey.getKeyType(); if (keyType == KeyType.RSA) { Sha256WithRsaSignature signature = new Sha256WithRsaSignature(); digestAlgorithm[0] = DigestAlgorithm.SHA256; signature.getKeyLocator().setType(KeyLocatorType.KEYNAME); signature.getKeyLocator().setKeyName(certificateName.getPrefix(-1)); return signature; } else if (keyType == KeyType.ECDSA) { Sha256WithEcdsaSignature signature = new Sha256WithEcdsaSignature(); digestAlgorithm[0] = DigestAlgorithm.SHA256; signature.getKeyLocator().setType(KeyLocatorType.KEYNAME); signature.getKeyLocator().setKeyName(certificateName.getPrefix(-1)); return signature; } else throw new SecurityException("Key type is not recognized"); }
/** * Generate a self-signed certificate for a public key. * * @param keyName The name of the public key. * @return The generated certificate. */ public IdentityCertificate selfSign(Name keyName) throws SecurityException { IdentityCertificate certificate = new IdentityCertificate(); Blob keyBlob = identityStorage_.getKey(keyName); PublicKey publicKey = new PublicKey(keyBlob); Calendar calendar = Calendar.getInstance(); double notBefore = (double) calendar.getTimeInMillis(); calendar.add(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. Logger.getLogger(IdentityManager.class.getName()).log(Level.SEVERE, null, ex); return null; } catch (DerDecodingException ex) { // We don't expect this to happen. Logger.getLogger(IdentityManager.class.getName()).log(Level.SEVERE, null, ex); return null; } signByCertificate(certificate, certificate.getName()); return certificate; }
/** * In table Key, set 'active' to isActive for the keyName. * * @param keyName The name of the key. * @param isActive The value for the 'active' field. */ protected void updateKeyStatus(Name keyName, boolean isActive) throws SecurityException { String keyId = keyName.get(-1).toEscapedString(); Name identityName = keyName.getPrefix(-1); try { PreparedStatement statement = database_.prepareStatement("UPDATE Key SET active=? WHERE " + 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); } }
/** * Check if the specified key already exists. * * @param keyName The name of the key. * @return true if the key exists, otherwise false. */ public final boolean doesKeyExist(Name keyName) throws SecurityException { String keyId = keyName.get(-1).toEscapedString(); Name identityName = keyName.getPrefix(-1); try { PreparedStatement statement = database_.prepareStatement(SELECT_doesKeyExist); statement.setString(1, identityName.toUri()); statement.setString(2, keyId); try { ResultSet result = statement.executeQuery(); if (result.next()) return result.getInt(1) > 0; else return false; } finally { statement.close(); } } catch (SQLException exception) { throw new SecurityException("BasicIdentityStorage: SQLite error: " + exception); } }
/** * Add a certificate to the identity storage. * * @param certificate The certificate to be added. This makes a copy of the certificate. * @throws SecurityException if the certificate is already installed. */ public final void addCertificate(IdentityCertificate certificate) throws SecurityException { checkAddCertificate(certificate); Name certificateName = certificate.getName(); Name keyName = certificate.getPublicKeyName(); // Insert the certificate. try { PreparedStatement statement = database_.prepareStatement( "INSERT INTO Certificate (cert_name, cert_issuer, identity_name, key_identifier, not_before, not_after, certificate_data) " + "values (?, ?, ?, ?, datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), ?)"); statement.setString(1, certificateName.toUri()); Name signerName = KeyLocator.getFromSignature(certificate.getSignature()).getKeyName(); statement.setString(2, signerName.toUri()); String keyId = keyName.get(-1).toEscapedString(); Name identity = keyName.getPrefix(-1); statement.setString(3, identity.toUri()); statement.setString(4, keyId); // Convert from milliseconds to seconds since 1/1/1970. statement.setLong(5, (long) (Math.floor(certificate.getNotBefore() / 1000.0))); statement.setLong(6, (long) (Math.floor(certificate.getNotAfter() / 1000.0))); // wireEncode returns the cached encoding if available. statement.setBytes(7, certificate.wireEncode().getImmutableArray()); try { statement.executeUpdate(); } finally { statement.close(); } } catch (SQLException exception) { throw new SecurityException("BasicIdentityStorage: SQLite error: " + exception); } }
/** * Get the public key DER blob from the identity storage. * * @param keyName The name of the requested public key. * @return The DER Blob. If not found, return a Blob with a null pointer. */ public final Blob getKey(Name keyName) throws SecurityException { if (!doesKeyExist(keyName)) return new Blob(); String keyId = keyName.get(-1).toEscapedString(); Name identityName = keyName.getPrefix(-1); try { PreparedStatement statement = database_.prepareStatement(SELECT_getKey); statement.setString(1, identityName.toUri()); statement.setString(2, keyId); try { ResultSet result = statement.executeQuery(); if (result.next()) return new Blob(result.getBytes("public_key")); else return new Blob(); } finally { statement.close(); } } catch (SQLException exception) { throw new SecurityException("BasicIdentityStorage: SQLite error: " + exception); } }
/** * Get the default certificate name for the specified key. * * @param keyName The key name. * @return The default certificate name. * @throws SecurityException if the default certificate name for the key name is not set. */ public final Name getDefaultCertificateNameForKey(Name keyName) throws SecurityException { String keyId = keyName.get(-1).toEscapedString(); Name identityName = keyName.getPrefix(-1); try { PreparedStatement statement = database_.prepareStatement(SELECT_getDefaultCertificateNameForKey); statement.setString(1, identityName.toUri()); statement.setString(2, keyId); try { ResultSet result = statement.executeQuery(); if (result.next()) return new Name(result.getString("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); } }
/** * Prepare an unsigned identity certificate. * * @param keyName The key name, e.g., `/{identity_name}/ksk-123456`. * @param publicKey The public key to sign. * @param signingIdentity The signing identity. * @param notBefore See IdentityCertificate. * @param notAfter See IdentityCertificate. * @param subjectDescription A list of CertificateSubjectDescription. See IdentityCertificate. If * null or empty, this adds a an ATTRIBUTE_NAME based on the keyName. * @param certPrefix The prefix before the `KEY` component. If null, this infers the certificate * name according to the relation between the 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-...`). * @return The unsigned IdentityCertificate, or null if the inputs are invalid. */ public final IdentityCertificate prepareUnsignedIdentityCertificate( Name keyName, PublicKey publicKey, Name signingIdentity, double notBefore, double notAfter, List subjectDescription, Name certPrefix) throws SecurityException { if (keyName.size() < 1) return null; String tempKeyIdPrefix = keyName.get(-1).toEscapedString(); if (tempKeyIdPrefix.length() < 4) return null; String keyIdPrefix = tempKeyIdPrefix.substring(0, 4); 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) Common.getNowMilliseconds()); else certName .append(keyName.getPrefix(-1)) .append("KEY") .append(keyName.get(-1)) .append("ID-CERT") .appendVersion((long) 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) Common.getNowMilliseconds()); else return null; } certificate.setName(certName); certificate.setNotBefore(notBefore); certificate.setNotAfter(notAfter); certificate.setPublicKeyInfo(publicKey); if (subjectDescription == null || subjectDescription.isEmpty()) certificate.addSubjectDescription( new CertificateSubjectDescription("2.5.4.41", keyName.getPrefix(-1).toUri())); else { for (int i = 0; i < subjectDescription.size(); ++i) certificate.addSubjectDescription( (CertificateSubjectDescription) subjectDescription.get(i)); } try { certificate.encode(); } catch (DerEncodingException ex) { throw new SecurityException("DerEncodingException: " + ex); } catch (DerDecodingException ex) { throw new SecurityException("DerDecodingException: " + ex); } return certificate; }