Now generating RSA keys.
This commit is contained in:
parent
b218591ea7
commit
2d026711c1
3 changed files with 62 additions and 10 deletions
|
|
@ -33,6 +33,7 @@ dependencies {
|
|||
implementation 'org.springframework.boot:spring-boot-starter-actuator'
|
||||
implementation 'org.springframework.shell:spring-shell-starter'
|
||||
implementation 'org.postgresql:postgresql'
|
||||
implementation 'org.bouncycastle:bcpkix-jdk18on:1.76'
|
||||
implementation 'org.thymeleaf:thymeleaf-spring5:3.1.2.RELEASE'
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||
testImplementation 'io.projectreactor:reactor-test'
|
||||
|
|
|
|||
|
|
@ -5,6 +5,12 @@ import lombok.Setter;
|
|||
import lombok.AccessLevel;
|
||||
import lombok.Data;
|
||||
import java.time.Instant;
|
||||
import java.security.KeyPair;
|
||||
import java.security.PublicKey;
|
||||
import org.bouncycastle.openssl.PEMWriter;
|
||||
import org.bouncycastle.util.io.pem.PemObject;
|
||||
import java.io.StringWriter;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* POJO for our Bot...
|
||||
|
|
@ -22,8 +28,35 @@ public class Bot {
|
|||
@Setter(AccessLevel.NONE)
|
||||
Instant published; // "2025-01-24T00:00:00Z",
|
||||
|
||||
/**
|
||||
* The RSA key for the bot... TODO: thinking, with separatation of data maybe
|
||||
* the private key should not be "exposed" here and instead we provide only
|
||||
* services to do key operations... keeping priv key data "secret" to the model
|
||||
*/
|
||||
@Setter(AccessLevel.NONE)
|
||||
String publicKeyPem; // "-----BEGIN PUBLIC KEY-----\\nMI [...] AB\\n-----END PUBLIC KEY-----"
|
||||
KeyPair keyPair;
|
||||
|
||||
/**
|
||||
* Get the string representation of the public key as required for the
|
||||
* ActivityPub key JSON.
|
||||
* "-----BEGIN PUBLIC KEY-----\\nMI [...] AB\\n-----END PUBLIC KEY-----"
|
||||
*/
|
||||
String getPublicKeyPEMString() {
|
||||
// Note: for performance it could be worth storing this in the db, or caching it in some way
|
||||
PublicKey pk = keyPair.getPublic();
|
||||
StringWriter w = new StringWriter();
|
||||
PEMWriter pw = new PEMWriter(w);
|
||||
try {
|
||||
pw.writeObject(new PemObject("PUBLIC KEY", pk.getEncoded()));
|
||||
pw.flush();
|
||||
pw.close();
|
||||
// TODO: flush and close with stringwriter?
|
||||
// Can an exception be thrown here using stringwriter?
|
||||
} catch (IOException e) {
|
||||
// FIXME: ?
|
||||
}
|
||||
return w.toString();
|
||||
}
|
||||
|
||||
@Setter(AccessLevel.NONE)
|
||||
String type = "Person";
|
||||
|
|
@ -36,17 +69,17 @@ public class Bot {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Bot: " + this.username;
|
||||
return "Bot: " + this.username + "\nKey: " + this.getPublicKeyPEMString() + "\n";
|
||||
}
|
||||
|
||||
Bot() {
|
||||
}
|
||||
Bot( String username, String name, String summary, Instant published, String publicKeyPem, String type, boolean manuallyApproveFollowers, boolean indexable ) {
|
||||
Bot( String username, String name, String summary, Instant published, KeyPair keyPair, String type, boolean manuallyApproveFollowers, boolean indexable ) {
|
||||
this.username = username;
|
||||
this.name = name;
|
||||
this.summary = summary;
|
||||
this.published = published;
|
||||
this.publicKeyPem = publicKeyPem;
|
||||
this.keyPair = keyPair;
|
||||
this.type = type;
|
||||
this.manuallyApproveFollowers = manuallyApproveFollowers;
|
||||
this.indexable = indexable;
|
||||
|
|
|
|||
|
|
@ -12,12 +12,18 @@ import lombok.Getter;
|
|||
import lombok.Setter;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
import java.security.PublicKey;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Our core Bot (aka user) data as stored persistently in the database.
|
||||
* Our core Bot (aka user, or 'actor') data as stored persistently in the database.
|
||||
* This is all the key non-derived data as required by the ActivityPub
|
||||
* specification. NOTE: This is not a comprehensive implementation!
|
||||
* specification. NOTE: This is not a comprehensive AP 'actor' implementation!
|
||||
*/
|
||||
@Slf4j
|
||||
@Entity
|
||||
@Table(name = "bot")
|
||||
@EntityListeners(AuditingEntityListener.class)
|
||||
|
|
@ -68,7 +74,7 @@ public class BotModel {
|
|||
|
||||
// TODO how and where do we generate this beastie?!?!
|
||||
@Column(nullable=true,unique=false) // FIXME: this isn't true, just easy for now
|
||||
@Getter private String publicKeyPem; // "-----BEGIN PUBLIC KEY-----\\nMI [...] AB\\n-----END PUBLIC KEY-----"
|
||||
@Getter private KeyPair keyPair;
|
||||
|
||||
@Column(nullable=false,unique=false)
|
||||
@Getter private String type;
|
||||
|
|
@ -87,12 +93,24 @@ public class BotModel {
|
|||
bm.type = bot.getType();
|
||||
bm.manuallyApproveFollowers = bot.isManuallyApproveFollowers();
|
||||
bm.indexable = bot.isIndexable();
|
||||
bm.publicKeyPem = bot.getPublicKeyPem();
|
||||
bm.keyPair = bot.getKeyPair();
|
||||
if ( bm.keyPair == null ) {
|
||||
// if a bot is created without a KeyPair is must be a new bot and needs a KeyPair
|
||||
// not confident this is the best place or way to do this, but "works for now"
|
||||
try {
|
||||
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
|
||||
generator.initialize(2048); // TODO: make this configurable?
|
||||
bm.keyPair = generator.generateKeyPair();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
// TODO: this should be pretty fatal to functionality really
|
||||
log.error("BotModel::from: NoSuchAlgorithm when creating: " + bot);
|
||||
}
|
||||
}
|
||||
return bm;
|
||||
}
|
||||
|
||||
Bot asBot() {
|
||||
return new Bot( username, name, summary, published, publicKeyPem, type, manuallyApproveFollowers, indexable );
|
||||
return new Bot( username, name, summary, published, keyPair, type, manuallyApproveFollowers, indexable );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue