Core components of the web application. https://write.as
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

62 lines
1.5 KiB

  1. package activitypub
  2. import (
  3. "crypto"
  4. "crypto/rsa"
  5. "crypto/x509"
  6. "encoding/pem"
  7. "fmt"
  8. "github.com/writeas/openssl-go"
  9. "log"
  10. )
  11. const keyBitSize = 2048
  12. // GenerateKeys creates an RSA keypair and returns the public and private key,
  13. // in that order.
  14. func GenerateKeys() (pubPEM []byte, privPEM []byte) {
  15. var err error
  16. privPEM, err = openssl.Call(nil, "genrsa", fmt.Sprintf("%d", keyBitSize))
  17. if err != nil {
  18. log.Printf("Unable to generate private key: %v", err)
  19. return nil, nil
  20. }
  21. pubPEM, err = openssl.Call(privPEM, "rsa", "-in", "/dev/stdin", "-pubout")
  22. if err != nil {
  23. log.Printf("Unable to get public key: %v", err)
  24. return nil, nil
  25. }
  26. return
  27. }
  28. func parsePrivateKey(der []byte) (crypto.PrivateKey, error) {
  29. if key, err := x509.ParsePKCS1PrivateKey(der); err == nil {
  30. return key, nil
  31. }
  32. if key, err := x509.ParsePKCS8PrivateKey(der); err == nil {
  33. switch key := key.(type) {
  34. case *rsa.PrivateKey:
  35. return key, nil
  36. default:
  37. return nil, fmt.Errorf("found unknown private key type in PKCS#8 wrapping")
  38. }
  39. }
  40. if key, err := x509.ParseECPrivateKey(der); err == nil {
  41. return key, nil
  42. }
  43. return nil, fmt.Errorf("failed to parse private key")
  44. }
  45. // DecodePrivateKey encodes public and private key to PEM format, returning
  46. // them in that order.
  47. func DecodePrivateKey(k []byte) (crypto.PrivateKey, error) {
  48. block, _ := pem.Decode(k)
  49. if block == nil || block.Type != "RSA PRIVATE KEY" {
  50. return nil, fmt.Errorf("failed to decode PEM block containing private key")
  51. }
  52. return parsePrivateKey(block.Bytes)
  53. }