certificate-api/routes/get.go

433 lines
13 KiB
Go
Raw Normal View History

2020-12-11 00:18:06 -05:00
package routes
import (
2021-07-02 16:57:38 -04:00
"golang.org/x/crypto/openpgp"
"golang.org/x/crypto/openpgp/armor"
"golang.org/x/crypto/openpgp/packet"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/rsa"
2020-12-11 00:18:06 -05:00
"crypto/sha1"
"crypto/tls"
"crypto/x509"
2020-12-11 00:18:06 -05:00
"encoding/hex"
2020-12-23 20:12:28 -05:00
"encoding/pem"
"io/ioutil"
2020-12-11 00:18:06 -05:00
"net/http"
2021-07-02 16:57:38 -04:00
"time"
"github.com/gin-gonic/gin"
2020-12-11 00:18:06 -05:00
)
2021-07-02 16:57:38 -04:00
type PGPKey struct {
FullName, Name, Comment, Email string
CreationTime time.Time
PublicKeyAlgorithm packet.PublicKeyAlgorithm
Fingerprint [20]byte
KeyID uint16
}
func GetOpenPGPInformationEncoded(c *gin.Context) {
query := c.Copy().Request.Body
block, err := armor.Decode(query)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"status": false,
"message": "Unable to parse body.",
})
return
}
pkt := packet.NewReader(block.Body)
entity, err := openpgp.ReadEntity(pkt)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"status": false,
"message": "Unable to parse body.",
})
return
}
if len(entity.Identities) > 1 {
c.JSON(http.StatusBadRequest, gin.H{
"status": false,
"message": "No identities found in PGP key.",
})
return
}
var key *PGPKey
for name, identity := range entity.Identities {
key = &PGPKey{
FullName: name,
Name: identity.UserId.Name,
Comment: identity.UserId.Comment,
Email: identity.UserId.Email,
CreationTime: entity.PrimaryKey.CreationTime,
PublicKeyAlgorithm: entity.PrimaryKey.PubKeyAlgo,
Fingerprint: entity.PrimaryKey.Fingerprint,
KeyID: uint16(entity.PrimaryKey.KeyId),
}
break
}
c.JSON(http.StatusOK, gin.H{
"status": true,
"fullName": key.FullName,
"name": key.Name,
"comment": key.Comment,
"email": key.Email,
"creationTime": key.CreationTime,
"publicKeyAlgorithm": key.PublicKeyAlgorithm,
"fingerprint": hex.EncodeToString(key.Fingerprint[:]),
"keyID": key.KeyID,
})
}
2020-12-23 20:12:28 -05:00
// GetCertificateInformationEncoded handler function for providing raw data to be parsed
func GetCertificateInformationEncoded(c *gin.Context) {
query := c.Copy().Request.Body
data, err := ioutil.ReadAll(query)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"status": false,
"message": "Unable to parse body.",
})
return
}
block, _ := pem.Decode(data)
if block == nil {
c.JSON(http.StatusBadRequest, gin.H{
"status": false,
"message": "Unable to decode PEM.",
})
return
}
certificate, err := x509.ParseCertificate(block.Bytes)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"status": false,
"message": "Unable to parse x509 data.",
})
return
}
var validationType string
for _, value := range certificate.PolicyIdentifiers {
if value.String() == "2.23.140.1.1" {
validationType = "EV"
} else if value.String() == "2.23.140.1.2.2" {
validationType = "OV"
} else if value.String() == "2.23.140.1.2.1" {
validationType = "DV"
}
}
keyUsages := []int{}
keyUsagesText := []string{}
extendedKeyUsages := []int{}
extendedKeyUsagesText := []string{}
for _, value := range certificate.ExtKeyUsage {
switch value {
case 0:
// All Usages
extendedKeyUsages = append(extendedKeyUsages, 0)
extendedKeyUsagesText = append(extendedKeyUsagesText, "Any/All Usages")
break
case 1:
// TLS Web Server Authentication
extendedKeyUsages = append(extendedKeyUsages, 1)
extendedKeyUsagesText = append(extendedKeyUsagesText, "TLS Web Server Authentication")
break
case 2:
// TLS Web Client Authentication
extendedKeyUsages = append(extendedKeyUsages, 2)
extendedKeyUsagesText = append(extendedKeyUsagesText, "TLS Web Client Authentication")
break
case 3:
// Code Signing
extendedKeyUsages = append(extendedKeyUsages, 3)
extendedKeyUsagesText = append(extendedKeyUsagesText, "Code Signing")
break
case 4:
// Email Protection
extendedKeyUsages = append(extendedKeyUsages, 4)
extendedKeyUsagesText = append(extendedKeyUsagesText, "Email Protection (S/MIME)")
default:
break
}
}
if certificate.KeyUsage&x509.KeyUsageCRLSign != 0 {
keyUsages = append(keyUsages, 0)
keyUsagesText = append(keyUsagesText, "CRL Signing")
}
if certificate.KeyUsage&x509.KeyUsageCertSign != 0 {
keyUsages = append(keyUsages, 1)
keyUsagesText = append(keyUsagesText, "Certificate Signing")
}
if certificate.KeyUsage&x509.KeyUsageContentCommitment != 0 {
keyUsages = append(keyUsages, 2)
keyUsagesText = append(keyUsagesText, "Content Commitment")
}
if certificate.KeyUsage&x509.KeyUsageDataEncipherment != 0 {
keyUsages = append(keyUsages, 3)
keyUsagesText = append(keyUsagesText, "Data Encipherment")
}
if certificate.KeyUsage&x509.KeyUsageDecipherOnly != 0 {
keyUsages = append(keyUsages, 4)
keyUsagesText = append(keyUsagesText, "Decipher Only")
}
if certificate.KeyUsage&x509.KeyUsageDigitalSignature != 0 {
keyUsages = append(keyUsages, 5)
keyUsagesText = append(keyUsagesText, "Digital Signature")
}
if certificate.KeyUsage&x509.KeyUsageEncipherOnly != 0 {
keyUsages = append(keyUsages, 6)
keyUsagesText = append(keyUsagesText, "Encipher Only")
}
if certificate.KeyUsage&x509.KeyUsageKeyAgreement != 0 {
keyUsages = append(keyUsages, 7)
keyUsagesText = append(keyUsagesText, "Key Agreement")
}
if certificate.KeyUsage&x509.KeyUsageKeyEncipherment != 0 {
keyUsages = append(keyUsages, 8)
keyUsagesText = append(keyUsagesText, "Key Encipherment")
}
sum := sha1.Sum(certificate.Raw)
var bitLength int
switch certificate.PublicKeyAlgorithm {
case x509.RSA:
if rsaKey, ok := certificate.PublicKey.(*rsa.PublicKey); ok {
bitLength = rsaKey.N.BitLen()
} else {
panic("expected rsa.PublicKey for type x509.RSA")
}
case x509.ECDSA:
if ecdsaKey, ok := certificate.PublicKey.(*ecdsa.PublicKey); ok {
bitLength = ecdsaKey.Params().BitSize
} else {
panic("expected ecdsa.PublicKey for type x509.ECDSA")
}
case x509.Ed25519:
bitLength = ed25519.PublicKeySize
}
2020-12-23 20:12:28 -05:00
c.JSON(http.StatusOK, gin.H{
"status": true,
"subject": gin.H{
"commonName": certificate.Subject.CommonName,
"organization": certificate.Subject.Organization,
"organizationalUnit": certificate.Subject.OrganizationalUnit,
"locality": certificate.Subject.Locality,
"country": certificate.Subject.Country,
},
"issuer": gin.H{
"commonName": certificate.Issuer.CommonName,
"organization": certificate.Issuer.Organization,
"organizationalUnit": certificate.Issuer.OrganizationalUnit,
"locality": certificate.Issuer.Locality,
"country": certificate.Issuer.Country,
},
"aia": gin.H{
"issuingCertificateURL": certificate.IssuingCertificateURL,
"ocspServer": certificate.OCSPServer,
},
2020-12-23 20:12:28 -05:00
"validationType": validationType,
"signatureAlgorithm": certificate.SignatureAlgorithm.String(),
"publicKeyAlgorithm": certificate.PublicKeyAlgorithm.String(),
2020-12-25 19:56:17 -05:00
"serialNumber": certificate.SerialNumber.String(),
"notBefore": certificate.NotBefore,
2020-12-23 20:12:28 -05:00
"notAfter": certificate.NotAfter,
"keyUsage": keyUsages,
"keyUsageAsText": keyUsagesText,
"extendedKeyUsage": extendedKeyUsages,
"extendedKeyUsageAsText": extendedKeyUsagesText,
"san": certificate.DNSNames,
"emailAddresses": certificate.EmailAddresses,
2020-12-23 20:12:28 -05:00
"fingerprint": hex.EncodeToString(sum[:]),
"bitLength": bitLength,
2020-12-23 20:12:28 -05:00
})
}
2020-12-11 00:18:06 -05:00
// GetCertificateInfo handler
func GetCertificateInfo(c *gin.Context) {
query := c.Query("q")
2020-12-25 21:40:32 -05:00
resp, err := tls.Dial("tcp", query+":443", &tls.Config{InsecureSkipVerify: true, PreferServerCipherSuites: true})
2020-12-11 00:18:06 -05:00
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"status": false,
"message": "Could not establish connection with server.",
})
return
}
cipherSuite := tls.CipherSuiteName(resp.ConnectionState().CipherSuite)
2020-12-22 19:12:11 -05:00
v := resp.ConnectionState().Version
var tlsVersion string
2020-12-22 19:12:11 -05:00
if v == tls.VersionSSL30 {
tlsVersion = "SSLv3"
2020-12-22 19:12:11 -05:00
} else if v == tls.VersionTLS10 {
tlsVersion = "TLSv1"
2020-12-22 19:12:11 -05:00
} else if v == tls.VersionTLS11 {
tlsVersion = "TLSv1.1"
2020-12-22 19:12:11 -05:00
} else if v == tls.VersionTLS12 {
tlsVersion = "TLSv1.2"
2020-12-22 19:12:11 -05:00
} else if v == tls.VersionTLS13 {
tlsVersion = "TLSv1.3"
} else {
tlsVersion = "unknown"
}
2020-12-11 00:18:06 -05:00
certificate := resp.ConnectionState().PeerCertificates[0]
2020-12-25 19:56:17 -05:00
rootCertificate := resp.ConnectionState().PeerCertificates[len(resp.ConnectionState().PeerCertificates)-1]
2020-12-11 00:18:06 -05:00
var validationType string
for _, value := range certificate.PolicyIdentifiers {
if value.String() == "2.23.140.1.1" {
validationType = "EV"
} else if value.String() == "2.23.140.1.2.2" {
validationType = "OV"
} else if value.String() == "2.23.140.1.2.1" {
validationType = "DV"
}
}
keyUsages := []int{}
keyUsagesText := []string{}
extendedKeyUsages := []int{}
extendedKeyUsagesText := []string{}
2020-12-11 00:18:06 -05:00
for _, value := range certificate.ExtKeyUsage {
switch value {
case 0:
// All Usages
extendedKeyUsages = append(extendedKeyUsages, 0)
extendedKeyUsagesText = append(extendedKeyUsagesText, "Any/All Usages")
2020-12-11 00:18:06 -05:00
break
case 1:
// TLS Web Server Authentication
extendedKeyUsages = append(extendedKeyUsages, 1)
extendedKeyUsagesText = append(extendedKeyUsagesText, "TLS Web Server Authentication")
2020-12-11 00:18:06 -05:00
break
case 2:
// TLS Web Client Authentication
extendedKeyUsages = append(extendedKeyUsages, 2)
extendedKeyUsagesText = append(extendedKeyUsagesText, "TLS Web Client Authentication")
2020-12-11 00:18:06 -05:00
break
case 3:
// Code Signing
extendedKeyUsages = append(extendedKeyUsages, 3)
extendedKeyUsagesText = append(extendedKeyUsagesText, "Code Signing")
2020-12-11 00:18:06 -05:00
break
case 4:
// Email Protection
extendedKeyUsages = append(extendedKeyUsages, 4)
extendedKeyUsagesText = append(extendedKeyUsagesText, "Email Protection (S/MIME)")
2020-12-11 00:18:06 -05:00
default:
break
}
}
2020-12-23 16:28:41 -05:00
if certificate.KeyUsage&x509.KeyUsageCRLSign != 0 {
keyUsages = append(keyUsages, 0)
keyUsagesText = append(keyUsagesText, "CRL Signing")
}
2020-12-23 16:28:41 -05:00
if certificate.KeyUsage&x509.KeyUsageCertSign != 0 {
keyUsages = append(keyUsages, 1)
keyUsagesText = append(keyUsagesText, "Certificate Signing")
}
2020-12-23 16:28:41 -05:00
if certificate.KeyUsage&x509.KeyUsageContentCommitment != 0 {
2020-12-23 20:12:28 -05:00
keyUsages = append(keyUsages, 2)
keyUsagesText = append(keyUsagesText, "Content Commitment")
}
2020-12-23 16:28:41 -05:00
if certificate.KeyUsage&x509.KeyUsageDataEncipherment != 0 {
2020-12-23 20:12:28 -05:00
keyUsages = append(keyUsages, 3)
keyUsagesText = append(keyUsagesText, "Data Encipherment")
}
2020-12-23 16:28:41 -05:00
if certificate.KeyUsage&x509.KeyUsageDecipherOnly != 0 {
2020-12-23 20:12:28 -05:00
keyUsages = append(keyUsages, 4)
keyUsagesText = append(keyUsagesText, "Decipher Only")
}
2020-12-23 16:28:41 -05:00
if certificate.KeyUsage&x509.KeyUsageDigitalSignature != 0 {
keyUsages = append(keyUsages, 5)
keyUsagesText = append(keyUsagesText, "Digital Signature")
}
2020-12-23 16:28:41 -05:00
if certificate.KeyUsage&x509.KeyUsageEncipherOnly != 0 {
keyUsages = append(keyUsages, 6)
keyUsagesText = append(keyUsagesText, "Encipher Only")
}
2020-12-23 16:28:41 -05:00
if certificate.KeyUsage&x509.KeyUsageKeyAgreement != 0 {
keyUsages = append(keyUsages, 7)
keyUsagesText = append(keyUsagesText, "Key Agreement")
}
2020-12-23 16:28:41 -05:00
if certificate.KeyUsage&x509.KeyUsageKeyEncipherment != 0 {
keyUsages = append(keyUsages, 8)
keyUsagesText = append(keyUsagesText, "Key Encipherment")
}
2020-12-11 00:18:06 -05:00
sum := sha1.Sum(certificate.Raw)
var bitLength int
switch certificate.PublicKeyAlgorithm {
case x509.RSA:
if rsaKey, ok := certificate.PublicKey.(*rsa.PublicKey); ok {
bitLength = rsaKey.N.BitLen()
} else {
panic("expected rsa.PublicKey for type x509.RSA")
}
case x509.ECDSA:
if ecdsaKey, ok := certificate.PublicKey.(*ecdsa.PublicKey); ok {
bitLength = ecdsaKey.Params().BitSize
} else {
panic("expected ecdsa.PublicKey for type x509.ECDSA")
}
}
2020-12-11 00:18:06 -05:00
c.JSON(http.StatusOK, gin.H{
"status": true,
"subject": gin.H{
"commonName": certificate.Subject.CommonName,
"organization": certificate.Subject.Organization,
"organizationalUnit": certificate.Subject.OrganizationalUnit,
"locality": certificate.Subject.Locality,
"country": certificate.Subject.Country,
},
"issuer": gin.H{
"commonName": certificate.Issuer.CommonName,
"organization": certificate.Issuer.Organization,
"organizationalUnit": certificate.Issuer.OrganizationalUnit,
"locality": certificate.Issuer.Locality,
"country": certificate.Issuer.Country,
},
2020-12-25 19:56:17 -05:00
"root": gin.H{
"commonName": rootCertificate.Issuer.CommonName,
"organization": rootCertificate.Issuer.Organization,
"organizationalUnit": rootCertificate.Issuer.OrganizationalUnit,
"locality": rootCertificate.Issuer.Locality,
"country": rootCertificate.Issuer.Country,
},
2021-07-01 21:24:44 -04:00
"aia": gin.H{
"issuingCertificateURL": certificate.IssuingCertificateURL,
"ocspServer": certificate.OCSPServer,
},
2020-12-23 16:28:41 -05:00
"validationType": validationType,
"signatureAlgorithm": certificate.SignatureAlgorithm.String(),
"publicKeyAlgorithm": certificate.PublicKeyAlgorithm.String(),
2020-12-25 19:56:17 -05:00
"serialNumber": certificate.SerialNumber.String(),
"notBefore": certificate.NotBefore,
2020-12-23 16:28:41 -05:00
"notAfter": certificate.NotAfter,
"keyUsage": keyUsages,
"keyUsageAsText": keyUsagesText,
"extendedKeyUsage": extendedKeyUsages,
"extendedKeyUsageAsText": extendedKeyUsagesText,
2020-12-23 16:28:41 -05:00
"san": certificate.DNSNames,
2021-07-01 21:24:44 -04:00
"emailAddresses": certificate.EmailAddresses,
2020-12-23 16:28:41 -05:00
"fingerprint": hex.EncodeToString(sum[:]),
"bitLength": bitLength,
"connection": gin.H{
2020-12-23 16:28:41 -05:00
"tlsVersion": tlsVersion,
"cipherSuite": cipherSuite,
},
2020-12-11 00:18:06 -05:00
})
}