Intial Commit

This commit is contained in:
2026-10-27 17:16:21 -04:00
parent 15f0a3fee1
commit 25f8486506
17 changed files with 645 additions and 1 deletions
+54
View File
@@ -0,0 +1,54 @@
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.security.*;
import java.security.spec.*;
import java.util.*;
/** Local Ed25519 ZBS signing; private key material is never printed or packaged. */
public class SignZBS {
public static void main(String[] args) throws Exception {
if(args.length<3) throw new IllegalArgumentException("init <key-directory> <SteamID64> | sign <key-directory> <jar>");
Path dir=Path.of(args[1]);
Path privatePath=dir.resolve("ed25519-private.der"), publicPath=dir.resolve("ed25519-public.der");
Path authorPath=dir.resolve("author.properties");
if(args[0].equals("init")) {
if(!args[2].matches("[0-9]{17}")) throw new IllegalArgumentException("Invalid SteamID64");
Files.createDirectories(dir);
if(Files.exists(privatePath)||Files.exists(publicPath)||Files.exists(authorPath))
throw new IllegalStateException("Signing identity already exists; reuse it rather than replacing it.");
KeyPair pair=KeyPairGenerator.getInstance("Ed25519").generateKeyPair();
Files.write(privatePath,pair.getPrivate().getEncoded(),StandardOpenOption.CREATE_NEW);
Files.write(publicPath,pair.getPublic().getEncoded(),StandardOpenOption.CREATE_NEW);
Files.writeString(authorPath,"steamID64="+args[2]+"\n",StandardOpenOption.CREATE_NEW);
Files.writeString(dir.resolve("public-profile-key.txt"),profileKey(pair.getPublic())+"\n",StandardOpenOption.CREATE_NEW);
System.out.println("Created dedicated Ed25519 ZombieBuddy signing identity for SteamID64 "+args[2]+".");
return;
}
if(!args[0].equals("sign")) throw new IllegalArgumentException("Unknown operation");
Properties author=new Properties();
try(var reader=Files.newBufferedReader(authorPath)) {author.load(reader);}
String sid=author.getProperty("steamID64");
if(sid==null||!sid.matches("[0-9]{17}")) throw new IllegalStateException("Invalid signing identity");
var factory=KeyFactory.getInstance("Ed25519");
var privateKey=factory.generatePrivate(new PKCS8EncodedKeySpec(Files.readAllBytes(privatePath)));
var publicKey=factory.generatePublic(new X509EncodedKeySpec(Files.readAllBytes(publicPath)));
Path jar=Path.of(args[2]);
String sha=HexFormat.of().formatHex(MessageDigest.getInstance("SHA-256").digest(Files.readAllBytes(jar)));
byte[] payload=("ZBS:"+sid+":"+sha).getBytes(StandardCharsets.UTF_8);
var signer=Signature.getInstance("Ed25519");signer.initSign(privateKey);signer.update(payload);
byte[] signature=signer.sign();
var verifier=Signature.getInstance("Ed25519");verifier.initVerify(publicKey);verifier.update(payload);
if(!verifier.verify(signature)) throw new IllegalStateException("Signing key pair does not match");
Path sidecar=Path.of(jar.toString()+".zbs");
Files.writeString(sidecar,"ZBS\nSteamID64:"+sid+"\nSignature:"+HexFormat.of().formatHex(signature)+"\n");
System.out.println("Signed and cryptographically verified "+jar.getFileName()+" (SteamID64 "+sid+").");
System.out.println("SHA-256: "+sha);
}
private static String profileKey(PublicKey key) {
byte[] encoded=key.getEncoded();
byte[] prefix=HexFormat.of().parseHex("302a300506032b6570032100");
if(encoded.length!=44||!Arrays.equals(prefix,Arrays.copyOf(encoded,12)))
throw new IllegalStateException("Unexpected Ed25519 public key encoding");
return "JavaModZBS:"+HexFormat.of().formatHex(Arrays.copyOfRange(encoded,12,44));
}
}