Git Product home page Git Product logo

pycvc's Introduction

pycvc

Card Verifiable Certificates (CVC) tools for Python

Introduction

Card Verifiable Certificates are an specification of storing electronic certificates, signed by RSA or Elliptic Curves algorithms.

In contrast to X509 certificates, CVC are more compact and are widely used by HSM cards or personal USB tokens.

pycvc implements the specifications of BSI TR 03110 to create CV certificates and requests.

pycvc can be used to make a CV request and deploy a PKI based on CVC.

pycvc also supports ECDH keys such as Curve25519 and Curve448.

Install

pip install pycvc

Usage

pycvc can be used by importing the package or calling the command line tools cvc-create, for CVC generation, and cvc-print, for displaying CVC information and verification.

For more information, execute cvc-create or cvc-print with --help flag.

Supported algorithms

  • RSA
  • ECDSA
  • EdDSA

Supported curves

  • secp192r1 (prime192v1)
  • secp224r1
  • secp256r1 (prime256v1)
  • secp384r1
  • secp521r1
  • brainpoolP256r1
  • brainpoolP384r1
  • brainpoolP512r1
  • secp256k1
  • ed25519
  • ed448

Supported schemes

  • ECDSA_SHA_1
  • ECDSA_SHA_224
  • ECDSA_SHA_256
  • ECDSA_SHA_384
  • ECDSA_SHA_512
  • RSA_v1_5_SHA_1
  • RSA_v1_5_SHA_256
  • RSA_v1_5_SHA_512
  • RSA_PSS_SHA_1
  • RSA_PSS_SHA_256
  • RSA_PSS_SHA_512
  • EDDSA

Here some examples.

Create a PKI with ECDSA

cvc-create is the tool to create certificates or requests. Call cvc-create --help for a complete list of parameters.

1- Setup the CA:

openssl ecparam -out ZZATCVCA00001.pem -name prime256v1 -genkey
openssl pkcs8 -topk8 -nocrypt -in ZZATCVCA00001.pem -outform DER -out ZZATCVCA00001.pkcs8
cvc-create --role=cvca --type=at --chr=ZZATCVCA00001 --days=365 --sign-key=ZZATCVCA00001.pkcs8 --scheme=ECDSA_SHA_256

2- Setup the DV:

openssl ecparam -out ZZATDVCA00001.pem -name prime256v1 -genkey
openssl pkcs8 -topk8 -nocrypt -in ZZATDVCA00001.pem -outform DER -out ZZATDVCA00001.pkcs8
openssl ec -in ZZATDVCA00001.pem -out ZZATDVCA00001.pub -pubout -outform DER
cvc-create --role=dv_domestic --type=at --chr=ZZATDVCA00001 --days=180 --sign-key=ZZATCVCA00001.pkcs8 --scheme=ECDSA_SHA_256 --sign-as=ZZATCVCA00001.cvcert --public-key=ZZATDVCA00001.pub

3- Create a certificate request

openssl ecparam -out ZZATTERM00001.pem -name prime256v1 -genkey
openssl pkcs8 -topk8 -nocrypt -in ZZATTERM00001.pem -outform DER -out ZZATTERM00001.pkcs8
cvc-create --chr=ZZATTERM00001 --scheme=ECDSA_SHA_256 --sign-key=ZZATTERM00001.pkcs8 --out-cert=ZZATTERM00001.cvreq --req-car=ZZATDVCA00001

4- Sign a certificate request

cvc-create --role=terminal --type=at --days=60 --sign-key=ZZATDVCA00001.pkcs8 --sign-as=ZZATDVCA00001.cvcert --request=ZZATTERM00001.cvreq

Create a PKI with RSA

cvc-create is the tool to create certificates or requests. Call cvc-create --help for a complete list of parameters.

1- Setup the CA:

openssl genrsa -out ZZATCVCA00001.pem 3072
openssl pkcs8 -topk8 -nocrypt -in ZZATCVCA00001.pem -outform DER -out ZZATCVCA00001.pkcs8
cvc-create --role=cvca --type=at --chr=ZZATCVCA00001 --days=365 --sign-key=ZZATCVCA00001.pkcs8 --scheme=RSA_v1_5_SHA_256

2- Setup the DV:

openssl genrsa -out ZZATDVCA00001.pem 2048
openssl pkcs8 -topk8 -nocrypt -in ZZATDVCA00001.pem -outform DER -out ZZATDVCA00001.pkcs8
openssl rsa -in ZZATDVCA00001.pem -out ZZATDVCA00001.pub -pubout -outform DER
cvc-create --role=dv_domestic --type=at --chr=ZZATDVCA00001 --days=180 --sign-key=ZZATCVCA00001.pkcs8 --scheme=RSA_v1_5_SHA_256 --sign-as=ZZATCVCA00001.cvcert --public-key=ZZATDVCA00001.pub

3- Create a certificate request

openssl genrsa -out ZZATTERM00001.pem 2048
openssl pkcs8 -topk8 -nocrypt -in ZZATTERM00001.pem -outform DER -out ZZATTERM00001.pkcs8
cvc-create --chr=ZZATTERM00001 --scheme=RSA_v1_5_SHA_256 --sign-key=ZZATTERM00001.pkcs8 --out-cert=ZZATTERM00001.cvreq --req-car=ZZATDVCA00001

4- Sign a certificate request

cvc-create --role=terminal --type=at --days=60 --sign-key=ZZATDVCA00001.pkcs8 --sign-as=ZZATDVCA00001.cvcert --request=ZZATTERM00001.cvreq

Create a PKI with EdDSA

cvc-create is the tool to create certificates or requests. Call cvc-create --help for a complete list of parameters.

1- Setup the CA:

openssl genpkey -algorithm Ed25519 -out ZZATCVCA00001.pem
openssl pkcs8 -topk8 -nocrypt -in ZZATCVCA00001.pem -outform DER -out ZZATCVCA00001.pkcs8
cvc-create --role=cvca --type=at --chr=ZZATCVCA00001 --days=365 --sign-key=ZZATCVCA00001.pkcs8

2- Setup the DV:

openssl genpkey -algorithm Ed25519 -out ZZATDVCA00001.pem
openssl pkcs8 -topk8 -nocrypt -in ZZATDVCA00001.pem -outform DER -out ZZATDVCA00001.pkcs8
openssl pkey -in ZZATDVCA00001.pem -out ZZATDVCA00001.pub -pubout -outform DER 2>/dev/null
cvc-create --role=dv_domestic --type=at --chr=ZZATDVCA00001 --days=180 --sign-key=ZZATCVCA00001.pkcs8 --sign-as=ZZATCVCA00001.cvcert --public-key=ZZATDVCA00001.pub

3- Create a certificate request

openssl genpkey -algorithm Ed25519 -out ZZATTERM00001.pem
openssl pkcs8 -topk8 -nocrypt -in ZZATTERM00001.pem -outform DER -out ZZATTERM00001.pkcs8
cvc-create --chr=ZZATTERM00001 --sign-key=ZZATTERM00001.pkcs8 --out-cert=ZZATTERM00001.cvreq --req-car=ZZATDVCA00001

4- Sign a certificate request

cvc-create --role=terminal --type=at --days=60 --sign-key=ZZATDVCA00001.pkcs8 --sign-as=ZZATDVCA00001.cvcert --request=ZZATTERM00001.cvreq

Validate certificates and requests

cvc-print is the tool for certificate validation and verification. Call cvc-print --help for a complete list of parameters.

The validation is performed by veryfing all signatures in the certificate chain.

1- Setup trust directory

mkdir certs
cp ZZATCVCA00001.cvcert certs/ZZATCVCA00001
cp ZZATDVCA00001.cvcert certs/ZZATDVCA00001

2- Validate certificates

$ cvc-print -d certs ZZATCVCA00001.cvcert
Certificate:
  Profile Identifier: 00
  CAR: ZZATCVCA00001
  Public Key:
    Scheme: ECDSA_SHA_256
    Public Point: 040e5e4d5f20ee36ac920132f7f448da353d826156e9cfd3075f9d877f9c172111a689953b9accd5011248be50ccf47480ab703b42382a7a45484fccdc738a82e7
  CHR: ZZATCVCA00001
  CHAT:
    Role:  TypeAT
    Bytes: c000000000
  Since:   2022-08-23
  Expires: 2023-08-23
Inner signature is VALID
Certificate VALID

$ cvc-print -d certs ZZATDVCA00001.cvcert
Certificate:
  Profile Identifier: 00
  CAR: ZZATCVCA00001
  Public Key:
    Scheme: ECDSA_SHA_256
    Public Point: 04b37a6588e55e9db3ea72837f4b4347028a51b1c5964ee54878bf2f856ee4abe06f1465e917c8d9ecf7170dbd61c2bc1fc37a1fa36698a33669daa6fa4c1e7400
  CHR: ZZATDVCA00001
  CHAT:
    Role:  TypeAT
    Bytes: 8000000000
  Since:   2022-08-23
  Expires: 2023-02-19
Inner signature is VALID
Certificate VALID

$ cvc-print -d certs ZZATTERM00001.cvreq
Certificate:
  Profile Identifier: 00
  CAR: ZZATTERM00001
  Public Key:
    Scheme: ECDSA_SHA_256
    Public Point: 0406358861bc93173b3931a07595eba2bbcc88b852ed0a7139067047ab8abdba9b28eb07344f4f4e8f375bdc886c86d32060e92541b4d73178f9c9c53d3d98a765
  CHR: ZZATTERM00001
Inner signature is VALID
Certificate VALID

$ cvc-print -d certs ZZATTERM00001.cvcert
Certificate:
  Profile Identifier: 00
  CAR: ZZATDVCA00001
  Public Key:
    Scheme: ECDSA_SHA_256
    Public Point: 0406358861bc93173b3931a07595eba2bbcc88b852ed0a7139067047ab8abdba9b28eb07344f4f4e8f375bdc886c86d32060e92541b4d73178f9c9c53d3d98a765
  CHR: ZZATTERM00001
  CHAT:
    Role:  TypeAT
    Bytes: 00
  Since:   2022-08-23
  Expires: 2022-10-22
Inner signature is VALID
Certificate VALID

pycvc's People

Contributors

polhenarejos avatar xoryouyou avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

pycvc's Issues

cvc-print: verification fails for RSA certificates

Thanks for fixing the issue I reported earlier. We have similar issue with RSA certificate verification. Data types expected and provided are different. Could you fix this one as well? Thanks.

Command: cvc-print -d certs ZZATCVCA00001.cvcert
Traceback: below

Traceback (most recent call last):
File "\Anaconda3\lib\runpy.py", line 197, in _run_module_as_main
return _run_code(code, main_globals, None,
File "
\Anaconda3\lib\runpy.py", line 87, in run_code
exec(code, run_globals)
File "*\Anaconda3\Scripts\cvc-print.exe_main
.py", line 7, in
File "\Anaconda3\lib\site-packages\cvc\tools\cvc_print.py", line 125, in run
main(args)
File \Anaconda3\lib\site-packages\cvc\tools\cvc_print.py", line 88, in main
if (CVC().decode(cdata).verify(cert_dir=cert_dir, dica=cdata if isreq else None)):
File "
\Anaconda3\lib\site-packages\cvc\certificates.py", line 188, in verify
pubkey = rsa.RSAPublicNumbers(ASN1().decode(puk).find(0x82).data(), ASN1().decode(puk).find(0x81).data()).public_key()
File "
\Anaconda3\lib\site-packages\cryptography\hazmat\primitives\asymmetric\rsa.py", line 395, in init
raise TypeError("RSAPublicNumbers arguments must be integers.")
TypeError: RSAPublicNumbers arguments must be integers.

can this tool support certificate generation for the card/ePassport?

See subject line.
Seems like the certificates that are generated are meant to be used in the terminal authentication protocol to authenticate the inspection system accessing data from a card. What changes will be required to generate certificates for the card itself which are verified by the inspection system to authenticate the card?

Generating RSA certificate for ECC public key

Can I generate RSA certificate for ECC public key? I want the terminal to have ECC private/public key pair but DV and CVCA to have RSA key pairs. In that case, can I generate RSA certificate for IS's ECC key pair? It doesn't seem it is supported but ideally should be possible.

Here is the batch script I am running:

SET seq=003
SET CA=DETestingCV
SET DV=DETESTDVDE
SET IS=DETESTISDE
SET SCHEME=RSA_v1_5_SHA_256
SET KEY_SIZE=2048

openssl genrsa -out %CA%%seq%.pem %KEY_SIZE%
openssl pkcs8 -topk8 -nocrypt -in %CA%%seq%.pem -outform DER -out %CA%%seq%.pkcs8
cvc-create --role=cvca --type=at --chr=%CA%%seq% --valid=365 --sign-key=%CA%%seq%.pkcs8 --scheme=%SCHEME%

openssl genrsa -out %DV%%seq%.pem %KEY_SIZE%
openssl pkcs8 -topk8 -nocrypt -in %DV%%seq%.pem -outform DER -out %DV%%seq%.pkcs8
openssl rsa -in %DV%%seq%.pem -out %DV%%seq%.pub -pubout -outform DER
cvc-create --role=dv_domestic --type=at --chr=%DV%%seq% --valid=180 --sign-key=%CA%%seq%.pkcs8 --scheme=%SCHEME% --sign-as=%CA%%seq%.cvcert --public-key=%DV%%seq%.pub

openssl ecparam -out %IS%%seq%.pem -name prime256v1 -genkey
openssl pkcs8 -topk8 -nocrypt -in %IS%%seq%.pem -outform DER -out %IS%%seq%.pkcs8
cvc-create --chr=%IS%%seq% --scheme=%SCHEME% --sign-key=%IS%%seq%.pkcs8 --out-cert=%IS%%seq%.cvreq --req-car=%DV%%seq%
cvc-create --role=terminal --type=at --valid=60 --sign-key=%DV%%seq%.pkcs8 --sign-as=%DV%%seq%.cvcert --request=%IS%%seq%.cvreq

and the error I am getting:

Traceback (most recent call last):
File "\Anaconda3\lib\runpy.py", line 197, in _run_module_as_main
return _run_code(code, main_globals, None,
File "
\Anaconda3\lib\runpy.py", line 87, in run_code
exec(code, run_globals)
File "*\Anaconda3\Scripts\cvc-create.exe_main
.py", line 7, in
File "\Anaconda3\lib\site-packages\cvc\tools\cvc_create.py", line 233, in run
main(args)
File "
\Anaconda3\lib\site-packages\cvc\tools\cvc_create.py", line 175, in main
pub_key = rsa.RSAPublicNumbers(int.from_bytes(CVC().decode(data).pubkey().find(0x82).data(), 'big'), int.from_bytes(CVC().decode(data).pubkey().find(0x81).data(), 'big')).public_key()
File "\Anaconda3\lib\site-packages\cryptography\hazmat\primitives\asymmetric\rsa.py", line 413, in public_key
return ossl.load_rsa_public_numbers(self)
File "
\Anaconda3\lib\site-packages\cryptography\hazmat\backends\openssl\backend.py", line 573, in load_rsa_public_numbers
rsa._check_public_key_components(numbers.e, numbers.n)
File "*\Anaconda3\lib\site-packages\cryptography\hazmat\primitives\asymmetric\rsa.py", line 201, in _check_public_key_components
raise ValueError("e must be odd.")
ValueError: e must be odd.

R and S components of ECDSA signature should be encoded to fixed number of bytes

I've run into a certificate which doesn't have correctly encoded signature for ECC algorithms. The problem is that the r and s components of ECDSA signature are encoded to minimum number of bytes required to fit those integers. However, they should be encoded to fixed number of bytes (derived based on the curve size, e.g. 32 bytes for P256, 28 bytes for P224, 24 bytes for P192, and so on). Could you please look into it and fix the issue?

From certificates.py:

    def sign(self, key, scheme):
        h,p = get_hash_padding(scheme)
        if (isinstance(key, ec.EllipticCurvePrivateKey)):
            signature = key.sign(self.__a.encode(), ec.ECDSA(h))
            r,s = utils.decode_dss_signature(signature)
            n = math.ceil(key.curve.key_size / 8)
            _**signature = r.to_bytes(n, 'big') + s.to_bytes(n, 'big')**_
        elif (isinstance(key, rsa.RSAPrivateKey)):
            signature = key.sign(self.__a.encode(), p, h)
        elif (isinstance(key, (ed25519.Ed25519PrivateKey, ed448.Ed448PrivateKey))):
            signature = key.sign(self.__a.encode())
        self.__a = self.__a.add_tag(0x5f37, bytearray(signature))
        return self

CHAT byte in the certificates is not correctly configured

To configure read/write access permissions/authorization for different data groups, we pass --read-dgX arguments from the commandline while creating the certificate which gets reflected in the CHAT data (tag 53 in the certificate object). I don't see these arguments changing anything. The bits corresponding to different data groups are always set to 0.
Can you fix this? Let me know if you need more detail.

CVC-CREATE: "--since" command line argument not supported

Even though the help content describes "--since" argument for valid_from date, it is not supported. Can we add the support for that? Can we also add support for valid_to date as well (in addition to # of days)?

Command: cvc-create --role=cvca --type=at --chr=ZZATCVCA00001 --since "2014/10/09" --valid=365 --sign-key=ZZATCVCA00001.pkcs8 --scheme=ECDSA_SHA_256

Traceback:
usage: cvc-create [-h] [--version] [-o FILENAME] [-r {cvca,dv_domestic,dv_foreign,terminal}] [-t {at,is,st}] [--valid VALID] -k FILENAME [--sign-as FILENAME] [--outer-as FILENAME] [--outer-key FILENAME]
[-p FILENAME] [-q FILENAME] [--out-key FILENAME]
[-s {ECDSA_SHA_1,ECDSA_SHA_224,ECDSA_SHA_256,ECDSA_SHA_384,ECDSA_SHA_512,RSA_v1_5_SHA_1,RSA_v1_5_SHA_256,RSA_v1_5_SHA_512,RSA_PSS_SHA_1,RSA_PSS_SHA_256,RSA_PSS_SHA_512}] [-c CHR]
[-a REQ_CAR] [--write-dg17] [--write-dg18] [--write-dg19] [--write-dg20] [--write-dg21] [--write-dg22] [--rfu31] [--psa] [--read-dg1] [--read-dg2] [--read-dg3] [--read-dg4] [--read-dg5]
[--read-dg6] [--read-dg7] [--read-dg8] [--read-dg9] [--read-dg10] [--read-dg11] [--read-dg12] [--read-dg13] [--read-dg14] [--read-dg15] [--read-dg16] [--read-dg17] [--read-dg18]
[--read-dg19] [--read-dg20] [--read-dg21] [--read-dg22] [--install-qual-cert] [--install-cert] [--pin-management] [--can-allowed] [--privileged] [--rid] [--verify-community]
[--verify-age] [--rfu5] [--rfu4] [--rfu3] [--rfu2] [--gen-qual-sig] [--gen-sig] [--read-iris] [--read-finger]
cvc-create: error: unrecognized arguments: --since 2014/10/09

Does pycvc support RSA-based certificate generation and verification?

I am trying to create RSA based certificate but running into this issue here:

File "*\Anaconda3\lib\site-packages\cvc\asn1.py", line 40, in make_tag
return to_bytes(tag) + ASN1.calculate_len(len(b)) + bytearray(b)
TypeError: object of type 'int' has no len()

Command I used with RSA-2K key generated using openssl:
cvc-create --role=cvca --type=at --chr=ZZATCVCA00001 --valid=365 --sign-key=ZZATCVCA00001.pkcs8 --scheme=RSA_v1_5_SHA_256

Does the package support RSA based certificates at all?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.