keys) {
load_directory(d, keys, null);
}
/**
* Load from a simple rt0 text format. A jabac extension. The format is
*
* # comments
* role <- role
*
*
* Spaces are not significant around the arrow and the tail can be as long
* as needed.
* @param s the InputStream to load
* @throws IOException if there is an error getting the file open or in
* format
*/
public void load_rt0(InputStream s)
throws IOException {
Pattern comment = Pattern.compile("(^\\s*#|^\\s*$)");
Pattern rule = Pattern.compile("([\\w\\.]+)\\s*<-+\\s*(.+)");
LineNumberReader r = new LineNumberReader(new InputStreamReader(s));
String line = null;
while ((line = r.readLine()) != null) {
Matcher cm = comment.matcher(line);
Matcher rm = rule.matcher(line);
if (cm.find()) continue;
if (rm.find())
add_credential(new InternalCredential(new Role(rm.group(1)),
new Role(rm.group(2))));
else
throw new IOException("Unexpected format: line " +
r.getLineNumber());
}
}
/**
* Equivalent to load_rt0(new FileInputStream(f)
* @param f the File to load
* @throws IOException if there is an error getting the file open
*/
public void load_rt0(File f) throws IOException {
load_rt0(new FileInputStream(f));
}
/**
* Write the certificates that make up the context as a zip file, with an
* entry for each credential or identity. The files are all zipped in a
* directory derived from the filename.
* @param s the OutputStream to write
* @param allIDs a boolean, if true write certificates for all Identities,
* whether used in signing a credential or not.
* @param withPrivateKeys a boolean, if true write the Identities as PEM
* file containing both the certificate and the private keys.
* @throws IOException if there is a problem writing the file.
*/
public void write_zip(OutputStream s, boolean allIDs,
boolean withPrivateKeys) throws IOException {
ZipOutputStream z = new ZipOutputStream(s);
Set ids = allIDs ? m_identities : new TreeSet();
String baseDir = "creds";
int idx = baseDir.indexOf('.');
if (idx != -1)
baseDir = baseDir.substring(0, idx);
int n = 0;
for (Credential c: credentials()) {
z.putNextEntry(new ZipEntry(baseDir + File.separator +
"attr" + n++ + c.getSuffix()));
c.write(z);
z.closeEntry();
if ( c.issuer() != null && !allIDs) ids.add(c.issuer());
}
for (Identity i: ids) {
z.putNextEntry(new ZipEntry(baseDir + File.separator +
i.getName() + ".pem"));
i.write(z);
if (withPrivateKeys)
i.writePrivateKey(z);
z.closeEntry();
}
z.close();
}
/**
* Equivalent to
* write_zip(new FileOutputStream(f), allIDs, withPrivateKeys).
* @param f the File to write
* @param allIDs a boolean, if true write certificates for all Identities,
* whether used in signing a credential or not.
* @param withPrivateKeys a boolean, if true write the Identities as PEM
* file containing both the certificate and the private keys.
* @throws IOException if there is a problem writing the file.
*/
public void write_zip(File f, boolean allIDs, boolean withPrivateKeys)
throws IOException {
write_zip(new FileOutputStream(f), allIDs, withPrivateKeys);
}
/**
* Write to a simple rt0 text format. A jabac extension.
* The format is
*
* role <- role
*
*
* @param w a Writer to print on
* @param useKeyIDs a boolean, true to print key IDs not mnemonics
*/
public void write_rt0(Writer w, boolean useKeyIDs) {
PrintWriter pw = w instanceof PrintWriter ?
(PrintWriter) w : new PrintWriter(w);
for (Credential c: credentials())
pw.println(useKeyIDs ? c.toString() : c.simpleString(this));
pw.flush();
}
/**
* Call write_rt0 on a FileWriter derived from f.
* @param f the File to write to
* @param useKeyIDs a boolean, true to print key IDs not mnemonics
* @throws IOException if there is a problem writing the file.
*/
public void write_rt0(File f, boolean useKeyIDs) throws IOException {
write_rt0(new FileWriter(f), useKeyIDs);
}
/**
* Equivalent to write_rt0(w, false);
* @param w a Writer to print on
*/
public void write_rt0(Writer w) { write_rt0(w, false); }
/**
* Equivalent to write_rt0(f, false);
* @param f the File to write to
* @throws IOException if there is a problem writing the file.
*/
public void write_rt0(File f) throws IOException {
write_rt0(new FileWriter(f), false);
}
/**
* Return this Context's CredentialFactory.
* @return this Context's CredentialFactory.
*/
public CredentialFactory getCredentialFactory() {
return credentialFactory;
}
/**
* Set this Context's CredentialFactory.
* @param cf the new CredentialFactoty
*/
public void setCredentialFactory(CredentialFactory cf) {
credentialFactory = cf;
}
/**
* Return a new credential supported by this Context. It is not inserted
* in the Context, but will have access to the context's keyid aliases.
* @param head a Role, the head of the encoded ABAC statement
* @param tail a Role, the tail of the decoded ABAC statement
* @return a Credential encoding that ABAC statement
*/
public Credential newCredential(Role head, Role tail) {
return credentialFactory.generateCredential(head, tail, keyMap);
}
/**
* Get to the SHA1 hash of the key. Used by Roles and Identities to get a
* key ID.
* @param k the PublicKey to get the ID from.
* @return a String with the key identifier
*/
static String extractKeyID(PublicKey k) {
SubjectPublicKeyInfo ki = extractSubjectPublicKeyInfo(k);
SubjectKeyIdentifier id =
SubjectKeyIdentifier.createSHA1KeyIdentifier(ki);
// Now format it into a string for keeps
Formatter fmt = new Formatter(new StringWriter());
for (byte b: id.getKeyIdentifier())
fmt.format("%02x", b);
return fmt.out().toString();
}
/**
* Extratct the SubjectPublicKeyInfo. Useful for some other encryptions,
* notably Certificate.make_cert().
* @param k the PublicKey to get the ID from.
* @return a String with the key identifier
*/
static SubjectPublicKeyInfo extractSubjectPublicKeyInfo(
PublicKey k) {
ASN1Sequence seq = null;
try {
seq = (ASN1Sequence) new ASN1InputStream(
k.getEncoded()).readObject();
}
catch (IOException ie) {
// Badly formatted key??
return null;
}
return new SubjectPublicKeyInfo(seq);
}
}