Skip to content

Commit

Permalink
Merge pull request #1 from KshitizFinbox/feature/uidai-okyc-validation
Browse files Browse the repository at this point in the history
feat: validations for UIDAI OKYC
  • Loading branch information
Kshitiz Agrawal authored May 16, 2024
2 parents c43000c + 4a4bef3 commit f32915f
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 109 deletions.
129 changes: 32 additions & 97 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,103 +1,38 @@
# goxmldsig

![Build Status](https://github.com/russellhaering/goxmldsig/actions/workflows/test.yml/badge.svg?branch=main)
[![GoDoc](https://godoc.org/github.com/russellhaering/goxmldsig?status.svg)](https://godoc.org/github.com/russellhaering/goxmldsig)

XML Digital Signatures implemented in pure Go.

## Installation

Install `goxmldsig` using `go get`:

```
$ go get github.com/russellhaering/goxmldsig
```

## Usage

Include the [`types.Signature`](https://pkg.go.dev/github.com/russellhaering/goxmldsig/types#Signature) struct from this package in your application messages.

```go
import (
sigtypes "github.com/russellhaering/goxmldsig/types"
)

type AppHdr struct {
...
Signature *sigtypes.Signature
}
```

### Signing
# I've spent days trying to wrap my mind over UIDAI's broken documentation over 3 languages (.net, Java, Python and now GoLang) to no good. Please don't waste yours. Use this snippet to validate Aadhaar Mobile and Email.

```go
package main

import (
"github.com/beevik/etree"
"github.com/russellhaering/goxmldsig"
)

func main() {
// Generate a key and self-signed certificate for signing
randomKeyStore := dsig.RandomKeyStoreForTest()
ctx := dsig.NewDefaultSigningContext(randomKeyStore)
elementToSign := &etree.Element{
Tag: "ExampleElement",
}
elementToSign.CreateAttr("ID", "id1234")

// Sign the element
signedElement, err := ctx.SignEnveloped(elementToSign)
if err != nil {
panic(err)
}

// Serialize the signed element. It is important not to modify the element
// after it has been signed - even pretty-printing the XML will invalidate
// the signature.
doc := etree.NewDocument()
doc.SetRoot(signedElement)
str, err := doc.WriteToString()
if err != nil {
panic(err)
}

println(str)
type PersonalInfoValidation struct {
MobileMatch bool `json:"mobile_match"`
EmailMatch bool `json:"email_match"`
}
```

### Signature Validation

```go
// Validate an element against a root certificate
func validate(root *x509.Certificate, el *etree.Element) {
// Construct a signing context with one or more roots of trust.
ctx := dsig.NewDefaultValidationContext(&dsig.MemoryX509CertificateStore{
Roots: []*x509.Certificate{root},
})

// It is important to only use the returned validated element.
// See: https://www.w3.org/TR/xmldsig-bestpractices/#check-what-is-signed
validated, err := ctx.Validate(el)
if err != nil {
panic(err)
}

doc := etree.NewDocument()
doc.SetRoot(validated)
str, err := doc.WriteToString()
if err != nil {
panic(err)
}

println(str)
func validatePersonalInfo(el *etree.Element, actualMobile, actualEmail, shareCode string, aadhaarLastDigit int) PersonalInfoValidation {
mobile := el.FindElement("//Poi").SelectAttrValue("m", "default-mobile")
email := el.FindElement("//Poi").SelectAttrValue("e", "default-email")

if aadhaarLastDigit == 0 {
aadhaarLastDigit = 1
}
var response PersonalInfoValidation

if mobile != "default-mobile" {
lastInput := actualMobile + shareCode
for i := 0; i < aadhaarLastDigit; i++ {
h := sha256.Sum256([]byte(lastInput))
lastInput = hex.EncodeToString(h[:])
}
response.MobileMatch = lastInput == mobile
}

if email != "default-email" {
lastInput := actualEmail + shareCode
for i := 0; i < aadhaarLastDigit; i++ {
h := sha256.Sum256([]byte(lastInput))
lastInput = hex.EncodeToString(h[:])
}
response.EmailMatch = lastInput == email
}

return response
}
```

## Limitations

This library was created in order to [implement SAML 2.0](https://github.com/russellhaering/gosaml2)
without needing to execute a command line tool to create and validate signatures. It currently
only implements the subset of relevant standards needed to support that implementation, but
I hope to make it more complete over time. Contributions are welcome.
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

## Reporting a Vulnerability

Security vulnerabilities can be reported using GitHub's [private vulnerability reporting tool](https://github.com/russellhaering/goxmldsig/security/advisories/new).
Security vulnerabilities can be reported using GitHub's [private vulnerability reporting tool](https://github.com/finbox-in/goxmldsig/security/advisories/new).
2 changes: 1 addition & 1 deletion canonicalize.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"sort"

"github.com/beevik/etree"
"github.com/russellhaering/goxmldsig/etreeutils"
"github.com/finbox-in/goxmldsig/etreeutils"
)

// Canonicalizer is an implementation of a canonicalization algorithm.
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module github.com/russellhaering/goxmldsig
module github.com/finbox-in/goxmldsig

go 1.15

Expand Down
2 changes: 1 addition & 1 deletion sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"fmt"

"github.com/beevik/etree"
"github.com/russellhaering/goxmldsig/etreeutils"
"github.com/finbox-in/goxmldsig/etreeutils"
)

type SigningContext struct {
Expand Down
16 changes: 9 additions & 7 deletions validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (
"regexp"

"github.com/beevik/etree"
"github.com/russellhaering/goxmldsig/etreeutils"
"github.com/russellhaering/goxmldsig/types"
"github.com/finbox-in/goxmldsig/etreeutils"
"github.com/finbox-in/goxmldsig/types"
)

var uriRegexp = regexp.MustCompile("^#[a-zA-Z_][\\w.-]*$")
Expand All @@ -29,6 +29,13 @@ type ValidationContext struct {
Clock *Clock
}

func NewUidaiOKYCValidationContext(certificateStore X509CertificateStore) *ValidationContext {
return &ValidationContext{
CertificateStore: certificateStore,
IdAttribute: DefaultIdAttr,
}
}

func NewDefaultValidationContext(certificateStore X509CertificateStore) *ValidationContext {
return &ValidationContext{
CertificateStore: certificateStore,
Expand Down Expand Up @@ -418,7 +425,6 @@ func (ctx *ValidationContext) findSignature(root *etree.Element) (*types.Signatu
}

func (ctx *ValidationContext) verifyCertificate(sig *types.Signature) (*x509.Certificate, error) {
now := ctx.Clock.Now()

roots, err := ctx.CertificateStore.Certificates()
if err != nil {
Expand Down Expand Up @@ -457,10 +463,6 @@ func (ctx *ValidationContext) verifyCertificate(sig *types.Signature) (*x509.Cer
return nil, errors.New("Could not verify certificate against trusted certs")
}

if now.Before(cert.NotBefore) || now.After(cert.NotAfter) {
return nil, errors.New("Cert is not valid at this time")
}

return cert, nil
}

Expand Down
2 changes: 1 addition & 1 deletion validate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"testing"

"github.com/beevik/etree"
"github.com/russellhaering/goxmldsig/etreeutils"
"github.com/finbox-in/goxmldsig/etreeutils"
"github.com/stretchr/testify/require"
)

Expand Down

0 comments on commit f32915f

Please sign in to comment.