If you're getting the error in golang when using the crypto/pkcs11
package, here is what you need to do:
Error decoding pfx: pkcs12: error reading P12 data: asn1: syntax error: indefinite length found (not DER)
Here is a good explanation of why this error happens. Steps to fix it below.
#!/bin/bash
# Script to convert old certificates (<2048 bits)
# to the new format compatible with OpenSSL 3.0+
# REF: https://stackoverflow.com/a/72600724/8313069
# Displays help
show_help() {
echo "Usage: $0 -i input_file -o output_file"
echo " -i input file in .pfx or .p12 format"
echo " -o output converted file"
echo "Requires OpenSSL 3.0+"
exit 1
}
# Reads parameters
while getopts ":i:o:" opt; do
case $opt in
i) infile="$OPTARG"
;;
o) outfile="$OPTARG"
;;
\?) show_help
;;
esac
done
# Checks if input and output informed
if [ -z "$infile" ] || [ -z "$outfile" ]; then
echo "Error: it is necessary to inform input and output file"
show_help
fi
# Checks OpenSSL version
openssl_version=$(openssl version | grep -oP 'OpenSSL \K\d+\.\d+\.\d+' | head -n1)
if dpkg --compare-versions "$openssl_version" "lt" "3.0"; then
echo "OpenSSL version $openssl_version not supported, requires 3.0+"
exit 1
fi
# Converts the certificate
intermediate=$(mktemp)
openssl pkcs12 -in "$infile" -nodes -provider legacy -provider default > "$intermediate"
openssl pkcs12 -in "$intermediate" -export -out "$outfile"
rm "$intermediate"
echo "Certificate successfully converted to $outfile"
Using the code below as reference. The default crypt library does not support the algorithm correctly. You'll get an error like:
INFO[0000] Error decoding pfx: pkcs12: unknown digest algorithm: 2.16.840.1.101.3.4.2.1
package main
import (
"io/ioutil"
log "github.com/sirupsen/logrus"
"golang.org/x/crypto/pkcs12"
)
func main() {
pfxBytes, err := ioutil.ReadFile("/tmp/cert.pfx")
if err != nil {
log.Info("Error reading file: ", err)
}
log.Info("File content: ", string(pfxBytes))
pfxPrivateKey, pfxCertificate, err := pkcs12.Decode(pfxBytes, "")
log.Info("PFX private key: ", pfxPrivateKey)
log.Info("PFX certificate: ", pfxCertificate)
if err != nil {
log.Info("Error decoding pfx: ", err)
}
}
To fix this, you'll need to use a third party library that supports it. The best and most well-maitained I've found is software.sslmate.com/src/go-pkcs12
.
Here I've fixed the code and added some tweaks like password verification.
package main
import (
log "github.com/sirupsen/logrus"
"io/ioutil"
"software.sslmate.com/src/go-pkcs12"
)
func main() {
pfxBytes, err := ioutil.ReadFile("/tmp/cert.pfx")
if err != nil {
log.Info("Error reading file: ", err)
}
log.Info("File content: ", string(pfxBytes))
pfxPrivateKey, pfxCertificate, err := pkcs12.Decode(pfxBytes, "")
log.Info("PFX private key: ", pfxPrivateKey)
log.Info("PFX certificate: ", pfxCertificate)
if err != nil {
log.Info("Error decoding pfx: ", err)
var isPasswordError bool = false
isPasswordError = err == pkcs12.ErrIncorrectPassword
log.Info("Is password error: ", isPasswordError)
}
}
I've spent wayy too much time on this. Diagnosing the problem and trying to figure out how it all worked.
The code I've posted here is MIT. Feel free to use it however you want.
If you have a contribution or comment, put it down below, I'll update the gist as soon as I have time.