github.com/haraldrudell/parl@v0.4.176/parlca/parse.go (about) 1 /* 2 © 2022–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/) 3 ISC License 4 */ 5 6 package parlca 7 8 import ( 9 "crypto/ecdsa" 10 "crypto/ed25519" 11 "crypto/rsa" 12 "crypto/x509" 13 "encoding/pem" 14 15 "github.com/haraldrudell/parl" 16 "github.com/haraldrudell/parl/perrors" 17 ) 18 19 func ParsePEM(pemData []byte) (certificate parl.Certificate, privateKey parl.PrivateKey, publicKey parl.PublicKey, err error) { 20 block, _ := pem.Decode(pemData) 21 if block == nil { 22 err = perrors.NewPF("PEM block not found in input") 23 return 24 } 25 switch block.Type { 26 case pemPublicKeyType: 27 publicKey, err = ParsePkix(block.Bytes) 28 return 29 case pemPrivateKeyType: 30 privateKey, err = ParsePkcs8(block.Bytes) 31 return 32 case pemCertificateType: 33 if _, err = x509.ParseCertificate(block.Bytes); perrors.IsPF(&err, "x509.ParseCertificate %w", err) { 34 return 35 } 36 certificate = &Certificate{der: block.Bytes} 37 return 38 default: 39 err = perrors.ErrorfPF("Unknown pem block type: %q", block.Type) 40 return 41 } 42 } 43 44 func ParsePkcs8(privateKeyDer parl.PrivateKeyDer) (privateKey parl.PrivateKey, err error) { 45 var pub any 46 if pub, err = x509.ParsePKCS8PrivateKey(privateKeyDer); perrors.IsPF(&err, "x509.ParsePKCS8PrivateKey %w", err) { 47 return 48 } 49 if pk, ok := pub.(*rsa.PrivateKey); ok { 50 privateKey = &RsaPrivateKey{PrivateKey: *pk} 51 } else if pk, ok := pub.(*ecdsa.PrivateKey); ok { 52 privateKey = &EcdsaPrivateKey{PrivateKey: *pk} 53 } else if pk, ok := pub.(ed25519.PrivateKey); ok { 54 privateKey = &Ed25519PrivateKey{PrivateKey: pk} 55 } else { 56 err = perrors.ErrorfPF("Unknown private key type: %T", pub) 57 } 58 return 59 } 60 61 func ParsePkix(publicKeyDer parl.PublicKeyDer) (publicKey parl.PublicKey, err error) { 62 var pub any 63 if pub, err = x509.ParsePKIXPublicKey(publicKeyDer); perrors.IsPF(&err, "x509.ParsePKIXPublicKey %w", err) { 64 return 65 } 66 if pk, ok := pub.(*rsa.PublicKey); ok { 67 publicKey = &RsaPublicKey{PublicKey: *pk} 68 } else if pk, ok := pub.(*ecdsa.PublicKey); ok { 69 publicKey = &EcdsaPublicKey{PublicKey: *pk} 70 } else if pk, ok := pub.(ed25519.PublicKey); ok { 71 publicKey = &Ed25519PublicKey{PublicKey: pk} 72 } else { 73 err = perrors.ErrorfPF("Unknown public key type: %T", pub) 74 } 75 return 76 }