Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
dviejokfs committed Jan 4, 2023
0 parents commit 5c8886f
Show file tree
Hide file tree
Showing 4 changed files with 274 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.idea
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module test-crts

go 1.18
163 changes: 163 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package main

import (
"bytes"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/sha256"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"log"
"math/big"
"time"
)

func parseX509Certificate(contents []byte) (*x509.Certificate, error) {
block, _ := pem.Decode(contents)
crt, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, err
}
return crt, nil
}

// compute Subject Key Identifier using RFC 7093, Section 2, Method 4
func computeSKI(privKey *ecdsa.PrivateKey) []byte {
// Marshall the public key
raw := elliptic.Marshal(privKey.Curve, privKey.PublicKey.X, privKey.PublicKey.Y)

// Hash it
hash := sha256.Sum256(raw)
return hash[:]
}
func CreateDefaultCA() (*x509.Certificate, *ecdsa.PrivateKey, error) {
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
log.Fatalf("Failed to generate serial number: %v", err)
return nil, nil, err
}
log.Printf("serialNumber: %v", serialNumber)
caPrivKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return nil, nil, err
}
expiry := 3650 * 24 * time.Hour
notBefore := time.Now().Round(time.Minute).Add(-5 * time.Minute).UTC()
template := x509.Certificate{
SerialNumber: serialNumber,
//Subject: pkix.Name{
// Organization: []string{"Kyma"},
// Country: []string{"DE"},
// Locality: []string{"Berlin"},
// OrganizationalUnit: []string{"Kyma"},
// StreetAddress: []string{"Karl-Liebknecht-Str. 3"},
// CommonName: "Kyma",
//},
NotBefore: notBefore,
NotAfter: notBefore.Add(expiry).UTC(),
//IsCA: true,
//SubjectKeyId: computeSKI(caPrivKey),
//ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
//KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign | x509.KeyUsageCRLSign | x509.KeyUsageKeyEncipherment,
BasicConstraintsValid: true,
}
subject := pkix.Name{
Organization: []string{"Kyma"},
//Country: []string{"US"},
//Locality: []string{"Berlin"},
//OrganizationalUnit: []string{"Kyma"},
//StreetAddress: []string{"Karl-Liebknecht-Str. 3"},
CommonName: "kyma",
}
template.IsCA = true
template.KeyUsage |= x509.KeyUsageDigitalSignature |
x509.KeyUsageKeyEncipherment | x509.KeyUsageCertSign |
x509.KeyUsageCRLSign
template.ExtKeyUsage = []x509.ExtKeyUsage{
x509.ExtKeyUsageClientAuth,
x509.ExtKeyUsageServerAuth,
}
template.Subject = subject
template.SubjectKeyId = computeSKI(caPrivKey)
caBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &caPrivKey.PublicKey, caPrivKey)
if err != nil {
return nil, nil, err
}
crt, err := x509.ParseCertificate(caBytes)
if err != nil {
return nil, nil, err
}
return crt, caPrivKey, nil
}
func EncodeX509Certificate(crt *x509.Certificate) []byte {
pemPk := pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: crt.Raw,
})
return pemPk

}
func main() {
caCert, _, err := CreateDefaultCA()
if err != nil {
log.Fatal(err)
}
_ = caCert
certToCheck := EncodeX509Certificate(caCert)
// certToCheck := []byte(`-----BEGIN CERTIFICATE-----
//MIICQTCCAeagAwIBAgIRAIlyPiTZkAYHopLI/MMzu5gwCgYIKoZIzj0EAwIwajEL
//MAkGA1UEBhMCRVMxETAPBgNVBAcTCEFsaWNhbnRlMREwDwYDVQQJEwhBbGljYW50
//ZTEZMBcGA1UEChMQS3VuZyBGdSBTb2Z0d2FyZTENMAsGA1UECxMEVGVjaDELMAkG
//A1UEAxMCY2EwHhcNMjMwMTAzMTA1NTIyWhcNMzMwMTA0MTA1NTIyWjBqMQswCQYD
//VQQGEwJFUzERMA8GA1UEBxMIQWxpY2FudGUxETAPBgNVBAkTCEFsaWNhbnRlMRkw
//FwYDVQQKExBLdW5nIEZ1IFNvZnR3YXJlMQ0wCwYDVQQLEwRUZWNoMQswCQYDVQQD
//EwJjYTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABB9O3T8iBC2OpFHe6BWJNEh4
//mxSR8AmyqKZKyjCLy9HnjDeYVoVQLK7Qouvc0iyTs+WTscv+iTkjzEkm9pfWdEqj
//bTBrMA4GA1UdDwEB/wQEAwIBpjAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUH
//AwEwDwYDVR0TAQH/BAUwAwEB/zApBgNVHQ4EIgQgV0rtlf59BQ7pjZHD+RF0zIIj
//mmgjUWR+6Q+npPY9mIcwCgYIKoZIzj0EAwIDSQAwRgIhAJqVsD9z4GSB26uKQNqW
//swGxS0xvdrwzJ8Wm/CKNPnBLAiEAkRuMG+YojjB/UKkArQEQNcxy8CzAUPoCbmG7
//cN2el6c=
//-----END CERTIFICATE-----`)
log.Printf("certToCheck: %s", certToCheck)
certPool := x509.NewCertPool()
parentCert, err := parseX509Certificate([]byte(certToCheck))
if err != nil {
log.Fatal(err)
}
_ = certPool.AppendCertsFromPEM([]byte(certToCheck))
x509Cert, err := parseX509Certificate([]byte(certToCheck))
if err != nil {
log.Fatal(err)
}
log.Printf("parentCert: %v", parentCert)
s := new(big.Int)
s = s.Set(GetCurveHalfOrdersAt(elliptic.P256()))
s = s.Add(s, big.NewInt(1))

lowS, err := IsLowS(parentCert.PublicKey.(*ecdsa.PublicKey), s)
if err != nil {
log.Fatal(err)
}

log.Printf("lowS: %v", lowS)
expectedSig, err := SignatureToLowS(parentCert.PublicKey.(*ecdsa.PublicKey), x509Cert.Signature)
if err != nil {
log.Fatal(err)
}
log.Printf("expectedSig: %v currentSig: %v", expectedSig, x509Cert.Signature)

equalSig := bytes.Equal(x509Cert.Signature, expectedSig)
log.Printf("equalSig: %v", equalSig)

options := x509.VerifyOptions{}
options.Roots = certPool
_, err = x509Cert.Verify(options)
if err != nil {
log.Fatal(err)
}
log.Printf("Hello, world.")
}
107 changes: 107 additions & 0 deletions utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package main

import (
"crypto/ecdsa"
"crypto/elliptic"
"encoding/asn1"
"errors"
"fmt"
"log"
"math/big"
)

type ECDSASignature struct {
R, S *big.Int
}

// curveHalfOrders contains the precomputed curve group orders halved.
// It is used to ensure that signature' S value is lower or equal to the
// curve group order halved. We accept only low-S signatures.
// They are precomputed for efficiency reasons.
var curveHalfOrders = map[elliptic.Curve]*big.Int{
elliptic.P224(): new(big.Int).Rsh(elliptic.P224().Params().N, 1),
elliptic.P256(): new(big.Int).Rsh(elliptic.P256().Params().N, 1),
elliptic.P384(): new(big.Int).Rsh(elliptic.P384().Params().N, 1),
elliptic.P521(): new(big.Int).Rsh(elliptic.P521().Params().N, 1),
}

func GetCurveHalfOrdersAt(c elliptic.Curve) *big.Int {
return big.NewInt(0).Set(curveHalfOrders[c])
}

func MarshalECDSASignature(r, s *big.Int) ([]byte, error) {
return asn1.Marshal(ECDSASignature{r, s})
}

func UnmarshalECDSASignature(raw []byte) (*big.Int, *big.Int, error) {
// Unmarshal
sig := new(ECDSASignature)
_, err := asn1.Unmarshal(raw, sig)
if err != nil {
return nil, nil, fmt.Errorf("failed unmashalling signature [%s]", err)
}

// Validate sig
if sig.R == nil {
return nil, nil, errors.New("invalid signature, R must be different from nil")
}
if sig.S == nil {
return nil, nil, errors.New("invalid signature, S must be different from nil")
}

if sig.R.Sign() != 1 {
return nil, nil, errors.New("invalid signature, R must be larger than zero")
}
if sig.S.Sign() != 1 {
return nil, nil, errors.New("invalid signature, S must be larger than zero")
}

return sig.R, sig.S, nil
}

func SignatureToLowS(k *ecdsa.PublicKey, signature []byte) ([]byte, error) {
r, s, err := UnmarshalECDSASignature(signature)
if err != nil {
return nil, err
}

s, err = ToLowS(k, s)
if err != nil {
return nil, err
}
log.Printf("SignatureToLowS: s [%s]", s)
return MarshalECDSASignature(r, s)
}

// IsLow checks that s is a low-S
func IsLowS(k *ecdsa.PublicKey, s *big.Int) (bool, error) {
halfOrder, ok := curveHalfOrders[k.Curve]
if !ok {
return false, fmt.Errorf("curve not recognized [%s]", k.Curve)
}

return s.Cmp(halfOrder) != 1, nil
}

func ToLowS(k *ecdsa.PublicKey, s *big.Int) (*big.Int, error) {
lowS, err := IsLowS(k, s)
if err != nil {
return nil, err
}

if !lowS {
// Set s to N - s that will be then in the lower part of signature space
// less or equal to half order
s.Sub(k.Params().N, s)

return s, nil
}

return s, nil
}

0 comments on commit 5c8886f

Please sign in to comment.