package encrypt import ( "bytes" "crypto/rand" "crypto/rsa" "crypto/x509" "crypto/x509/pkix" "encoding/pem" "errors" "fmt" "math/big" "time" ) // No envelope here; server/UI define their own payload structs. func parsePeerPublicKey(pemOrCert string) (*rsa.PublicKey, error) { block, _ := pem.Decode([]byte(pemOrCert)) if block == nil { return nil, errors.New("no PEM block found") } switch block.Type { case "PUBLIC KEY": k, err := x509.ParsePKIXPublicKey(block.Bytes) if err != nil { return nil, err } rsaPub, ok := k.(*rsa.PublicKey) if !ok { return nil, errors.New("expecting RSA PUBLIC KEY") } return rsaPub, nil case "RSA PUBLIC KEY": return x509.ParsePKCS1PublicKey(block.Bytes) case "CERTIFICATE": c, err := x509.ParseCertificate(block.Bytes) if err != nil { return nil, err } rsaPub, ok := c.PublicKey.(*rsa.PublicKey) if !ok { return nil, errors.New("certificate does not contain RSA key") } return rsaPub, nil default: return nil, fmt.Errorf("unsupported PEM type: %s", block.Type) } } func ParsePeerPublicKey(pemOrCert string) (*rsa.PublicKey, error) { return parsePeerPublicKey(pemOrCert) } func generateSelfSignedCert(priv *rsa.PrivateKey, commonName string) ([]byte, error) { if commonName == "" { commonName = "Encryptor Local Identity" } tpl := &x509.Certificate{ SerialNumber: big.NewInt(time.Now().UnixNano()), Subject: pkix.Name{CommonName: commonName}, NotBefore: time.Now().Add(-1 * time.Hour), NotAfter: time.Now().AddDate(1, 0, 0), KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, BasicConstraintsValid: true, } der, err := x509.CreateCertificate(rand.Reader, tpl, tpl, &priv.PublicKey, priv) if err != nil { return nil, err } buf := &bytes.Buffer{} _ = pem.Encode(buf, &pem.Block{Type: "CERTIFICATE", Bytes: der}) return buf.Bytes(), nil }