spacemonkeygo / openssl

OpenSSL bindings for Go
http://godoc.org/github.com/spacemonkeygo/openssl
Apache License 2.0
473 stars 236 forks source link

Unable to get the md5 subject_hash #112

Closed kevin-liangit closed 5 years ago

kevin-liangit commented 5 years ago

Hi all,

First time posting here. I am looking to get the subject_hash (md5) for my pem file, as you would with command line openssl

wmachs-iphone:platform-tools user$ openssl x509 -noout -subject_hash_old -in ../charles-ssl-proxying-certificate.pem e64b345

I tried using the spacemonkey library but was not successful. What am I doing wrong?

data,_ :=ioutil.ReadFile("/Users/kevinliang/Desktop/charles-ssl-proxying-certificate.pem")

newMd5,err:=openssl.NewMD5Hash()
pemfile,_ := openssl.LoadCertificateFromPEM(data)
pemblock,err:=pemfile.MarshalPEM()
_=err
newMd5.Write(pemblock)
fmt.Println(newMd5.Sum())
val,_:=newMd5.Sum()
fmt.Println(hex.EncodeToString(val[:]))

RESPONSE

[150 21 143 243 26 230 95 234 154 135 143 103 234 127 200 228] d41d8cd98f00b204e9800998ecf8427e

azdagron commented 5 years ago

Hello.

The hash produced by -subject_hash_old is not a hash over the entire certificate (which is what your code is calculating). It is instead an md5 hash of the asn.1 encoding of the certificate subject extension (the first four bytes of the digest are then stuffed into an uint32 in little endian ordering). You don't need this library to accomplish this. Here is some code that does this (error checking is omitted):

$ openssl x509 -noout -subject_hash_old -in cacert.pem
543b6ca4
$ go run subhash.go cacert.pem
543b6ca4
$ cat subhash.go
package main

import (
    "crypto/md5"
    "crypto/x509"
    "encoding/asn1"
    "encoding/binary"
    "encoding/pem"
    "fmt"
    "io/ioutil"
    "os"
)

func main() {
    pemBytes, _ := ioutil.ReadFile(os.Args[1])
    block, _ := pem.Decode(pemBytes)
    cert, _ := x509.ParseCertificate(block.Bytes)

    sub, _ := asn1.Marshal(cert.Subject.ToRDNSequence())
    digest := md5.Sum(sub)

    hash := binary.LittleEndian.Uint32(digest[:4])

    fmt.Printf("%x\n", hash)
}
kevin-liangit commented 5 years ago

thanks azdraon. No luck but I do want to point out that my cert is in the format as so:

-----BEGIN CERTIFICATE----- BLOCK -----END CERTIFICATE-----

azdagron commented 5 years ago

The code above expects that format. If you fill in the error handling, is the code failing at one of the steps above?

kevin-liangit commented 5 years ago

kevins-mbp:CSVReader kevinliang$ go run hash.go 68880a30

this is the response i get, so no error. Oddly when i outpued the error it did complain at

block,err4 := pem.Decode(pemBytes)

if err!=nil{
    fmt.Println(err, "ERROR")
}
azdagron commented 5 years ago

your error handling above is not correct. try the following:

package main

import (
    "crypto/md5"
    "crypto/x509"
    "encoding/asn1"
    "encoding/binary"
    "encoding/pem"
    "errors"
    "fmt"
    "io/ioutil"
    "os"
)

func main() {
    if err := run(); err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }
}

func run() error {
    if len(os.Args) < 2 {
        return errors.New("missing path to certificate")
    }

    pemBytes, err := ioutil.ReadFile(os.Args[1])
    if err != nil {
        return fmt.Errorf("unable to open certificate: %v", err)
    }

    block, _ := pem.Decode(pemBytes)
    if block == nil {
        return errors.New("failed to decode PEM")
    }

    cert, err := x509.ParseCertificate(block.Bytes)
    if err != nil {
        return fmt.Errorf("failed to parse certificate from PEM: %v", err)
    }

    sub, err := asn1.Marshal(cert.Subject.ToRDNSequence())
    if err != nil {
        return fmt.Errorf("failed to asn.1 encode certificate subject: %v", err)
    }

    digest := md5.Sum(sub)

    hash := binary.LittleEndian.Uint32(digest[:4])

    fmt.Printf("%x\n", hash)
    return nil
}
kevin-liangit commented 5 years ago

I am still getting 68880a30 , there was zero error output

wmachs-iphone:platform-tools kevinliang$ openssl x509 -noout -subject_hash -in ../charles-ssl-proxying-certificate.pem e3f5f47d wmachs-iphone:platform-tools kevinliang$ openssl x509 -noout -subject_hash_old -in ../charles-ssl-proxying-certificate.pem e64b3453

azdagron commented 5 years ago

¯_(ツ)_/¯

Not sure what is happening exactly. If I had your certificate I could probably figure it out. In any case, if you are interested in the exact behavior of openssl, you could always add some methods to the Certificate struct (in this library) that wrap the X509_subject_name_hash and X509_subject_name_hash_old methods out of openssl (with appropriate stubs, since X509_subject_name_hash_old didn't always exist, and is also not available if MD5 support is compiled out of openssl).

Colduction commented 1 week ago

You could use my repo for doing this: rsa

There are both subject_hash_old and issuer_hash_old