74 lines
2.2 KiB
Python
74 lines
2.2 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Generate Ed25519 keypair for node with stable printable outputs.
|
|
Primary purpose: provide a portable alternative to OpenSSL-based generation.
|
|
If 'cryptography' is unavailable, gracefully degrade with exit code 0 but no output, so caller can fallback.
|
|
|
|
Outputs JSON to stdout on success:
|
|
{
|
|
"private_key_pem": "...",
|
|
"public_key_pem": "...",
|
|
"public_key_hex": "....",
|
|
"node_id": "node-...",
|
|
}
|
|
|
|
Exit codes:
|
|
0 - success OR graceful degrade (no output) when cryptography not available
|
|
1 - unexpected error
|
|
|
|
Note: We intentionally avoid printing anything besides the JSON on success.
|
|
"""
|
|
|
|
import sys
|
|
import json
|
|
|
|
try:
|
|
from cryptography.hazmat.primitives.asymmetric import ed25519
|
|
from cryptography.hazmat.primitives import serialization
|
|
from cryptography.hazmat.backends import default_backend
|
|
except Exception:
|
|
# cryptography not available - graceful degradation: no output, caller will fallback
|
|
sys.exit(0)
|
|
|
|
|
|
def main():
|
|
try:
|
|
# Generate Ed25519 keypair
|
|
private_key = ed25519.Ed25519PrivateKey.generate()
|
|
public_key = private_key.public_key()
|
|
|
|
private_pem = private_key.private_bytes(
|
|
encoding=serialization.Encoding.PEM,
|
|
format=serialization.PrivateFormat.PKCS8,
|
|
encryption_algorithm=serialization.NoEncryption(),
|
|
).decode("utf-8")
|
|
|
|
public_pem = public_key.public_bytes(
|
|
encoding=serialization.Encoding.PEM,
|
|
format=serialization.PublicFormat.SubjectPublicKeyInfo,
|
|
).decode("utf-8")
|
|
|
|
# Extract raw 32-byte public key
|
|
public_der = public_key.public_bytes(
|
|
encoding=serialization.Encoding.DER,
|
|
format=serialization.PublicFormat.SubjectPublicKeyInfo,
|
|
)
|
|
# The last 32 bytes are the raw key for Ed25519
|
|
public_key_hex = public_der[-32:].hex()
|
|
|
|
node_id = f"node-{public_key_hex[:16]}"
|
|
|
|
print(json.dumps({
|
|
"private_key_pem": private_pem,
|
|
"public_key_pem": public_pem,
|
|
"public_key_hex": public_key_hex,
|
|
"node_id": node_id,
|
|
}))
|
|
return 0
|
|
except Exception:
|
|
# Do not spam stdout; caller will fallback to OpenSSL path
|
|
return 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main()) |