Crypt-PKCS10

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN


VERSION

    version 1.800201

SYNOPSIS

        use Crypt::PKCS10;
    
        Crypt::PKCS10->setAPIversion( 1 );
        my $decoded = Crypt::PKCS10->new( $csr ) or die Crypt::PKCS10->error;
    
        print $decoded;
    
        @names = $decoded->extensionValue('subjectAltName' );
        @names = $decoded->subject unless( @names );
    
        %extensions = map { $_ => $decoded->extensionValue( $_ ) } $decoded->extensions

DESCRIPTION

    Crypt::PKCS10 parses PKCS #10 certificate requests (CSRs) and provides
    accessor methods to extract the data in usable form.

    Common object identifiers will be translated to their corresponding
    names. Additionally, accessor methods allow extraction of single data
    fields. The format of returned data varies by accessor.

README  view on Meta::CPAN


    For ECC: Crypt::PK::ECC

    Very old CSRs may require DIGEST::MD{5,4,2}

METHODS

    Access methods may exist for subject name components that are not
    listed here. To test for these, use code of the form:

      $locality = $decoded->localityName if( $decoded->can('localityName') );

    If a name component exists in a CSR, the method will be present. The
    converse is not (always) true.

 class method setAPIversion( $version )

    Selects the API version (0 or 1) expected.

    Must be called before calling any other method.

README  view on Meta::CPAN


    If a file handle is supplied, the caller should specify acceptPEM => 0
    if the contents are DER.

    The request may be PEM or binary DER encoded. Only one request is
    processed.

    If PEM, other data (such as mail headers) may precede or follow the
    CSR.

        my $decoded = Crypt::PKCS10->new( $csr ) or die Crypt::PKCS10->error;

    Returns undef if there is an I/O error or the request can not be parsed
    successfully.

    Call error() to obtain more detail.

  options

    The options are specified as name => value.

README  view on Meta::CPAN


    In array context, returns an array of (componentName, [values]) pairs.
    Abbreviations are not used.

    Note that the order of components in a name is significant.

  commonName

    Returns the common name(s) from the subject.

        my $cn = $decoded->commonName();

  organizationalUnitName

    Returns the organizational unit name(s) from the subject

  organizationName

    Returns the organization name(s) from the subject.

  emailAddress

README  view on Meta::CPAN

 signatureAlgorithm

    Returns the signature algorithm according to its object identifier.

 signatureParams

    Returns the parameters associated with the signatureAlgorithm as
    binary. Returns undef if none, or if NULL.

    Note: In the future, some signatureAlgorithms may return a hashref of
    decoded fields.

    Callers are advised to check for a ref before decoding...

 signature( $format )

    The CSR's signature is returned.

    If $format is 1, in binary.

    If $format is 2, decoded as an ECDSA signature - returns hashref to r
    and s.

    Otherwise, in its hexadecimal representation.

 attributes( $name )

    A request may contain a set of attributes. The attributes are OIDs with
    values. The most common is a list of requested extensions, but other
    OIDs can also occur. Of those, challengePassword is typical.

README  view on Meta::CPAN

    In scalar context, a single string is returned, which may include lists
    and labels.

      cspName="Microsoft Strong Cryptographic Provider",keySpec=2,signature=("",0)

    Special characters are escaped as described in options.

    In array context, the value(s) are returned as a list of items, which
    may be references.

     print( " $_: ", scalar $decoded->attributes($_), "\n" )
                                       foreach ($decoded->attributes);

    See the module documentation for a list of known OID names.

    It is too long to include here.

 extensions

    Returns an array containing the names of all extensions present in the
    CSR. If no extensions are present, the empty list is returned.

    The names vary depending on the API version; however, the returned
    names are acceptable to extensionValue, extensionPresent, and name2oid.

    The values of extensions vary, however the following code fragment will
    dump most extensions and their value(s).

     print( "$_: ", $decoded->extensionValue($_,1), "\n" ) foreach ($decoded->extensions);

    The sample code fragment is not guaranteed to handle all cases.
    Production code needs to select the extensions that it understands and
    should respect the critical boolean. critical can be obtained with
    extensionPresent.

 extensionValue( $name, $format )

    Returns the value of an extension by name, e.g. extensionValue(
    'keyUsage' ). The name SHOULD be an API v1 name, but API v0 names are

README.md  view on Meta::CPAN

# NAME

Crypt::PKCS10 - parse PKCS #10 certificate requests

# SYNOPSIS

    use Crypt::PKCS10;

    Crypt::PKCS10->setAPIversion( 1 );
    my $decoded = Crypt::PKCS10->new( $csr ) or die Crypt::PKCS10->error;

    print $decoded;

    @names = $decoded->extensionValue('subjectAltName' );
    @names = $decoded->subject unless( @names );

    %extensions = map { $_ => $decoded->extensionValue( $_ ) } $decoded->extensions

# DESCRIPTION

`Crypt::PKCS10` parses PKCS #10 certificate requests (CSRs) and provides accessor methods to extract the data in usable form.

Common object identifiers will be translated to their corresponding names.
Additionally, accessor methods allow extraction of single data fields.
The format of returned data varies by accessor.

The access methods return the value corresponding to their name.  If called in scalar context, they return the first value (or an empty string).  If called in array context, they return all values.

**true** values should be specified as 1 and **false** values as 0.  Future API changes may provide different functions when other values are used.

# METHODS

Access methods may exist for subject name components that are not listed here.  To test for these, use code of the form:

    $locality = $decoded->localityName if( $decoded->can('localityName') );

If a name component exists in a CSR, the method will be present.  The converse is not (always) true.

## class method setAPIversion( $version )

Selects the API version (0 or 1) expected.

Must be called before calling any other method.

The API version determines how a CSR is parsed.  Changing the API version after

README.md  view on Meta::CPAN

`$csr` may be a scalar containing the request, a file name, or a file handle from which to read it.

If a file name is specified, the `readFile` option must be specified.

If a file handle is supplied, the caller should specify `acceptPEM => 0` if the contents are DER.

The request may be PEM or binary DER encoded.  Only one request is processed.

If PEM, other data (such as mail headers) may precede or follow the CSR.

    my $decoded = Crypt::PKCS10->new( $csr ) or die Crypt::PKCS10->error;

Returns `undef` if there is an I/O error or the request can not be parsed successfully.

Call `error()` to obtain more detail.

### options

The options are specified as `name => value`.

If the first option is a HASHREF, it is expanded and any remaining options are added.

README.md  view on Meta::CPAN

        ]
    ];

This structure can be used directly to assemble ASN1 structures with
the OpenXPKI::Crypt::\* objects.

### commonName

Returns the common name(s) from the subject.

    my $cn = $decoded->commonName();

### organizationalUnitName

Returns the organizational unit name(s) from the subject

### organizationName

Returns the organization name(s) from the subject.

### emailAddress

README.md  view on Meta::CPAN


## signatureAlgorithm

Returns the signature algorithm according to its object identifier.

## signatureParams

Returns the parameters associated with the **signatureAlgorithm** as binary.
Returns **undef** if none, or if **NULL**.

Note: In the future, some **signatureAlgorithm**s may return a hashref of decoded fields.

Callers are advised to check for a ref before decoding...

## signature( $format )

The CSR's signature is returned.

If `$format` is **1**, in binary.

If `$format` is **2**, decoded as an ECDSA signature - returns hashref to `r` and `s`.

Otherwise, in its hexadecimal representation.

## attributes( $name )

A request may contain a set of attributes. The attributes are OIDs with values.
The most common is a list of requested extensions, but other OIDs can also
occur.  Of those, **challengePassword** is typical.

For API version 0, this method returns a hash consisting of all

README.md  view on Meta::CPAN

as a numeric OID.

In scalar context, a single string is returned, which may include lists and labels.

    cspName="Microsoft Strong Cryptographic Provider",keySpec=2,signature=("",0)

Special characters are escaped as described in options.

In array context, the value(s) are returned as a list of items, which may be references.

    print( " $_: ", scalar $decoded->attributes($_), "\n" )
                                      foreach ($decoded->attributes);

See the _Table of known OID names_ below for a list of names.

## extensions

Returns an array containing the names of all extensions present in the CSR.  If no extensions are present,
the empty list is returned.

The names vary depending on the API version; however, the returned names are acceptable to `extensionValue`, `extensionPresent`, and `name2oid`.

The values of extensions vary, however the following code fragment will dump most extensions and their value(s).

    print( "$_: ", $decoded->extensionValue($_,1), "\n" ) foreach ($decoded->extensions);

The sample code fragment is not guaranteed to handle all cases.
Production code needs to select the extensions that it understands and should respect
the **critical** boolean.  **critical** can be obtained with extensionPresent.

## extensionValue( $name, $format )

Returns the value of an extension by name, e.g. `extensionValue( 'keyUsage' )`.
The name SHOULD be an API v1 name, but API v0 names are accepted for compatibility.
The name can also be specified as a numeric OID.

lib/Crypt/PKCS10.pm  view on Meta::CPAN


    $pkinfo->{algorithm}{algorithm}
        = $oids{$pkinfo->{algorithm}{algorithm}}
	  if( defined $pkinfo->{algorithm}{algorithm}
	    && exists $oids{$pkinfo->{algorithm}{algorithm}} );
    return $pkinfo;
}

# OIDs requiring some sort of special handling
#
# Called with decoded value, returns updated value.
# Key is ASN macro name

my %special;
%special =
(
 EnhancedKeyUsage => sub {
     my $self = shift;
     my( $value, $id ) = @_;

     foreach (@{$value}) {

lib/Crypt/PKCS10.pm  view on Meta::CPAN

    }
    }
    return $typeandvalues;
}

sub _convert_extensionRequest {
    my $self = shift;
    my( $extensionRequest ) = @_;

    my $parser = $self->_init('extensionRequest');
    my $decoded = $parser->decode($extensionRequest) or return [];

    foreach my $entry (@{$decoded}) {
	my $name = $oids{ $entry->{extnID} };
	$name = $variantNames{$name} if( defined $name && exists $variantNames{$name} );
        if (defined $name) {
	    my $asnName = $name;
	    $asnName =~ tr/ //d;
            my $parser = $self->_init($asnName, 1);
            if(!$parser) {
                $entry = undef;
                next;
            }

lib/Crypt/PKCS10.pm  view on Meta::CPAN


	    $self->_scanvalue( $dec );

	    if( exists $special{$asnName} ) {
		my $action = $special{$asnName};
		$dec = $action->( $self, $dec, $asnName, $entry );
	    }
	    $entry->{extnValue} = $dec;
        }
    }
    @{$decoded} = grep { defined } @{$decoded};
    return $decoded;
}

sub _convert_rdn {
    my $self = shift;
    my $typeandvalue = shift;
    my %hash = ( _subject => [], );
    foreach my $entry ( @$typeandvalue ) {
	foreach my $item (@$entry) {
	    my $oid = $item->{type};
	    my $name = (exists $variantNames{$oid})? $variantNames{$oid}[1]: $oids{ $oid };

lib/Crypt/PKCS10.pm  view on Meta::CPAN


    # For RSA PSS the parameters have been parsed to a hash already
    if (ref $self->{signatureAlgorithm}{parameters} eq 'HASH') {
        return $self->{signatureAlgorithm}{parameters};
    }

    my( $tlen, undef, $tag ) = asn_decode_tag2( $self->{signatureAlgorithm}{parameters} );
    if( $tlen != 0 && $tag != ASN_NULL ) {
        return $self->{signatureAlgorithm}{parameters}
    }
    # Known algorithm's parameters MAY return a hash of decoded fields.
    # For now, leaving that to the caller...

    return;
}

sub signature {
    my $self = shift;
    my $format = shift;

    if( defined $format && $format == 2 ) { # Per keytype decoding

lib/Crypt/PKCS10.pm  view on Meta::CPAN


Very old CSRs may require C<DIGEST::MD{5,4,2}>

=end :readme

=head1 SYNOPSIS

    use Crypt::PKCS10;

    Crypt::PKCS10->setAPIversion( 1 );
    my $decoded = Crypt::PKCS10->new( $csr ) or die Crypt::PKCS10->error;

    print $decoded;

    @names = $decoded->extensionValue('subjectAltName' );
    @names = $decoded->subject unless( @names );

    %extensions = map { $_ => $decoded->extensionValue( $_ ) } $decoded->extensions

=head1 DESCRIPTION

C<Crypt::PKCS10> parses PKCS #10 certificate requests (CSRs) and provides accessor methods to extract the data in usable form.

Common object identifiers will be translated to their corresponding names.
Additionally, accessor methods allow extraction of single data fields.
The format of returned data varies by accessor.

The access methods return the value corresponding to their name.  If called in scalar context, they return the first value (or an empty string).  If called in array context, they return all values.

B<true> values should be specified as 1 and B<false> values as 0.  Future API changes may provide different functions when other values are used.

=head1 METHODS

Access methods may exist for subject name components that are not listed here.  To test for these, use code of the form:

  $locality = $decoded->localityName if( $decoded->can('localityName') );

If a name component exists in a CSR, the method will be present.  The converse is not (always) true.

=head2 class method setAPIversion( $version )

Selects the API version (0 or 1) expected.

Must be called before calling any other method.

The API version determines how a CSR is parsed.  Changing the API version after

lib/Crypt/PKCS10.pm  view on Meta::CPAN

C<$csr> may be a scalar containing the request, a file name, or a file handle from which to read it.

If a file name is specified, the C<readFile> option must be specified.

If a file handle is supplied, the caller should specify C<< acceptPEM => 0 >> if the contents are DER.

The request may be PEM or binary DER encoded.  Only one request is processed.

If PEM, other data (such as mail headers) may precede or follow the CSR.

    my $decoded = Crypt::PKCS10->new( $csr ) or die Crypt::PKCS10->error;

Returns C<undef> if there is an I/O error or the request can not be parsed successfully.

Call C<error()> to obtain more detail.

=head3 options

The options are specified as C<< name => value >>.

If the first option is a HASHREF, it is expanded and any remaining options are added.

lib/Crypt/PKCS10.pm  view on Meta::CPAN

        ]
    ];

This structure can be used directly to assemble ASN1 structures with
the OpenXPKI::Crypt::* objects.

=head3 commonName

Returns the common name(s) from the subject.

    my $cn = $decoded->commonName();

=head3 organizationalUnitName

Returns the organizational unit name(s) from the subject

=head3 organizationName

Returns the organization name(s) from the subject.

=head3 emailAddress

lib/Crypt/PKCS10.pm  view on Meta::CPAN


=head2 signatureAlgorithm

Returns the signature algorithm according to its object identifier.

=head2 signatureParams

Returns the parameters associated with the B<signatureAlgorithm> as binary.
Returns B<undef> if none, or if B<NULL>.

Note: In the future, some B<signatureAlgorithm>s may return a hashref of decoded fields.

Callers are advised to check for a ref before decoding...

=head2 signature( $format )

The CSR's signature is returned.

If C<$format> is B<1>, in binary.

If C<$format> is B<2>, decoded as an ECDSA signature - returns hashref to C<r> and C<s>.

Otherwise, in its hexadecimal representation.

=head2 attributes( $name )

A request may contain a set of attributes. The attributes are OIDs with values.
The most common is a list of requested extensions, but other OIDs can also
occur.  Of those, B<challengePassword> is typical.

For API version 0, this method returns a hash consisting of all

lib/Crypt/PKCS10.pm  view on Meta::CPAN

as a numeric OID.

In scalar context, a single string is returned, which may include lists and labels.

  cspName="Microsoft Strong Cryptographic Provider",keySpec=2,signature=("",0)

Special characters are escaped as described in options.

In array context, the value(s) are returned as a list of items, which may be references.

 print( " $_: ", scalar $decoded->attributes($_), "\n" )
                                   foreach ($decoded->attributes);


=for readme stop

See the I<Table of known OID names> below for a list of names.

=for readme continue

=begin :readme

lib/Crypt/PKCS10.pm  view on Meta::CPAN


=head2 extensions

Returns an array containing the names of all extensions present in the CSR.  If no extensions are present,
the empty list is returned.

The names vary depending on the API version; however, the returned names are acceptable to C<extensionValue>, C<extensionPresent>, and C<name2oid>.

The values of extensions vary, however the following code fragment will dump most extensions and their value(s).

 print( "$_: ", $decoded->extensionValue($_,1), "\n" ) foreach ($decoded->extensions);


The sample code fragment is not guaranteed to handle all cases.
Production code needs to select the extensions that it understands and should respect
the B<critical> boolean.  B<critical> can be obtained with extensionPresent.

=head2 extensionValue( $name, $format )

Returns the value of an extension by name, e.g. C<extensionValue( 'keyUsage' )>.
The name SHOULD be an API v1 name, but API v0 names are accepted for compatibility.

t/02_base.t  view on Meta::CPAN

use warnings;

use Test::More 0.94;

use File::Spec;

# Name of directory where data files are found

my @dirpath = (File::Spec->splitpath( $0 ))[0,1];

my $decoded;

plan  tests => 12;

# Basic functions test requires RSA

# Some useful information for automated testing reports

my $sslver = eval {
    local $SIG{__WARN__} = sub {};

t/02_base.t  view on Meta::CPAN

FjpgWH5b3xQHVyjknpteOZJnICHmlMHcwqX1uk+ywC3hRTcC/+k+wtnbs0hvCh6c
t17iTm9qI8Tlf4xhHFrsXeCOCmtN3/HSjy3c9dYVB/je5JDesYWiDy1Ssp5D/Fg9
OwC37p57VNLEyCj397q/bdQtd9wkMQKbYTMOC1Wm3Mco9XOvGW/evs20t4xINjbk
xTf+NvadhsWn4CRnKkUEyqOivkjokf9Lg7SBXqaXL1Q2dGbezOa+lMZ67QQUU5Jo
RyYABCGHIzz=
-----END CERTIFICATE REQUEST-----
trailing junk
more junk
-CERT-

    $decoded = eval { Crypt::PKCS10->new( undef, dieOnError => 1, verifySignature => 0 ) };
    like( $@, qr/^\$csr argument to new\(\) is not defined at /, "dieOnError generates exception" ) or BAIL_OUT( Crypt::PKCS10->error );

    $decoded = eval { Crypt::PKCS10->new( undef, verifySignature => 0 ); 1 };
    like( $@, qr/^Value of Crypt::PKCS10->new ignored at /, "new() in void context generates exception" ) or BAIL_OUT( Crypt::PKCS10->error );

    $decoded = Crypt::PKCS10->new( $csr, PEMonly => 1, verifySignature => 0 );

    isnt( $decoded, undef, 'load PEM from variable' ) or BAIL_OUT( Crypt::PKCS10->error );

    isa_ok( $decoded, 'Crypt::PKCS10' ); # Make sure new objects are blessed

    is( $decoded->version, "v1", 'CSR version' );

    is( $decoded->commonName, "test", 'CSR commonName' );

    is( $decoded->emailAddress, 'test@test.com', 'emailAddress' );

    is( $decoded->subjectPublicKey, '3082010a0282010100e0484c12ee29a56fb72d2829fdf286859b049a007' .
	'd9030126bdd1e9d2319be38b4a40b00416dc54b000340ba580bb1c511e251e1a781ec2139c52d41e16226f6' .
	'07d1c4b3027a4a951eadc88e90b100de568f267902c694399d1392b27b7a7f31d84795e51d6833ee46132bf' .
	'c049f9f962cc6f50e511f1a56227d47d7e3d60f8756d914a8fcf5440a67e571e4106fa6e6cb1cbe6e46b94a' .
	'bed62f11bde4b2cfb2cf330558654e7f27ccc82b28708517a3336a36a9308b5683cbf3dcca492cd563ae3a7' .
	'4d2d337424a644771cce8704dc47e67ecff2389587a57e3a2197813114a58cecd260071bf03c97aa4b2d0bf' .
	'0e1f51310202bc7dee79ba9e884a6528a36f0203010001', 'hex subjectPublicKey' );

    is( $decoded->subjectPublicKey(1), << '_KEYPEM_', 'PEM subjectPublicKey' );
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4EhMEu4ppW+3LSgp/fKG
hZsEmgB9kDASa90enSMZvji0pAsAQW3FSwADQLpYC7HFEeJR4aeB7CE5xS1B4WIm
9gfRxLMCekqVHq3IjpCxAN5WjyZ5AsaUOZ0TkrJ7en8x2EeV5R1oM+5GEyv8BJ+f
lizG9Q5RHxpWIn1H1+PWD4dW2RSo/PVECmflceQQb6bmyxy+bka5Sr7WLxG95LLP
ss8zBVhlTn8nzMgrKHCFF6MzajapMItWg8vz3MpJLNVjrjp00tM3QkpkR3HM6HBN
xH5n7P8jiVh6V+OiGXgTEUpYzs0mAHG/A8l6pLLQvw4fUTECArx97nm6nohKZSij
bwIDAQAB
-----END PUBLIC KEY-----
_KEYPEM_

    is_deeply( $decoded->subjectPublicKeyParams,
               {keytype => 'RSA',
                keylen => 2048,
                modulus => 'e0484c12ee29a56fb72d2829fdf286859b049a007d9030126bdd1e9d2319be38b4a40b00416dc54b000340ba580bb1c511e251e1a781ec2139c52d41e16226f607d1c4b3027a4a951eadc88e90b100de568f267902c694399d1392b27b7a7f31d84795e51d6833ee46132bfc049f9f...
                publicExponent => '10001',
               }, 'subjectPublicKeyParams(RSA)' );

    is( $decoded->signature, 'dc8ba14eade00b952cdaacf0f48986407f01802b3d2c626c0cea42f977a39c3dbb5' .
	'8db01c1897fb72a3d46c811269e446c4c208f63030694216f84ecca99163a60587e5bdf14075728e49e9b5e3' .
	'992672021e694c1dcc2a5f5ba4fb2c02de1453702ffe93ec2d9dbb3486f0a1e9cb75ee24e6f6a23c4e57f8c6' .
	'11c5aec5de08e0a6b4ddff1d28f2ddcf5d61507f8dee490deb185a20f2d52b29e43fc583d3b00b7ee9e7b54d' .
	'2c4c828f7f7babf6dd42d77dc2431029b61330e0b55a6dcc728f573af196fdebecdb4b78c483636e4c537fe3' .
	'6f69d86c5a7e024672a4504caa3a2be48e891ff4b83b4815ea6972f54367466decce6be94c67aed04145392684726',
	'signature' );

    is( unpack( "H*", $decoded->certificationRequest ),
        '308201b602010030818831133011060a0992268993f22c64011916036f726731173015060a0992268993f22c' .
        '64011916074f70656e53534c31153013060a0992268993f22c640119160575736572733123300b0603550403' .
        '0c04746573743014060a0992268993f22c6401010c06313233343536311c301a06092a864886f70d01090116' .
        '0d7465737440746573742e636f6d30820122300d06092a864886f70d01010105000382010f003082010a0282' .
        '010100e0484c12ee29a56fb72d2829fdf286859b049a007d9030126bdd1e9d2319be38b4a40b00416dc54b00' .
        '0340ba580bb1c511e251e1a781ec2139c52d41e16226f607d1c4b3027a4a951eadc88e90b100de568f267902' .
        'c694399d1392b27b7a7f31d84795e51d6833ee46132bfc049f9f962cc6f50e511f1a56227d47d7e3d60f8756' .
        'd914a8fcf5440a67e571e4106fa6e6cb1cbe6e46b94abed62f11bde4b2cfb2cf330558654e7f27ccc82b2870' .
        '8517a3336a36a9308b5683cbf3dcca492cd563ae3a74d2d337424a644771cce8704dc47e67ecff2389587a57' .
        'e3a2197813114a58cecd260071bf03c97aa4b2d0bf0e1f51310202bc7dee79ba9e884a6528a36f0203010001a000',
        'certificationRequest' );

    is( scalar $decoded->subject, '/DC=org/DC=OpenSSL/DC=users/CN=test/UID=123456/emailAddress=test@test.com',
	'subject()' );

    is_deeply( $decoded->subjectRaw, [
          {
            'value' => 'org',
            'type' => '0.9.2342.19200300.100.1.25',
            'format' => 'ia5String'
          },
          {
            'value' => 'OpenSSL',
            'type' => '0.9.2342.19200300.100.1.25',
            'format' => 'ia5String'
          },

t/02_base.t  view on Meta::CPAN

            }
          ],
          {
            'format' => 'ia5String',
            'value' => 'test@test.com',
            'type' => '1.2.840.113549.1.9.1'
          }
        ],
	    'subjectRaw()' );

    is( scalar $decoded->userID, '123456', 'userID accessor autoloaded' );

    # Note that this is the input, but with junk removed.

    my $extcsr = << '~~~';
-----BEGIN CERTIFICATE REQUEST-----
MIICzjCCAbYCAQAwgYgxEzARBgoJkiaJk/IsZAEZFgNvcmcxFzAVBgoJkiaJk/Is
ZAEZFgdPcGVuU1NMMRUwEwYKCZImiZPyLGQBGRYFdXNlcnMxIzALBgNVBAMMBHRl
c3QwFAYKCZImiZPyLGQBAQwGMTIzNDU2MRwwGgYJKoZIhvcNAQkBFg10ZXN0QHRl
c3QuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4EhMEu4ppW+3
LSgp/fKGhZsEmgB9kDASa90enSMZvji0pAsAQW3FSwADQLpYC7HFEeJR4aeB7CE5

t/02_base.t  view on Meta::CPAN

      "\340\13\225,\332\254\360\364\211\206\@\177\1\200+=,bl\f\352B\371w\243\234=\273X" .
      "\333\1\301\211\177\267*=F\310\21&\236DlL \217c\3\6\224!o\204\354\312\231\26:`X~[" .
      "\337\24\aW(\344\236\233^9\222g !\346\224\301\334\302\245\365\272O\262\300-\341E7\2" .
      "\377\351>\302\331\333\263Ho\n\36\234\267^\342Noj#\304\345\177\214a\34Z\354]\340\216" .
      "\nkM\337\361\322\217-\334\365\326\25\a\370\336\344\220\336\261\205\242\17-R\262" .
      "\236C\374X=;\0\267\356\236{T\322\304\310(\367\367\272\277m\324-w\334\$1\2\233a3\16" .
      "\13U\246\334\307(\365s\257\31o\336\276\315\264\267\214H66\344\3057\3766\366\235\206" .
      "\305\247\340\$g*E\4\312\243\242\276H\350\221\377K\203\264\201^\246\227/T6tf\336\314" .
      "\346\276\224\306z\355\4\24S\222hG&";

    is( $decoded->csrRequest(1), $extcsr, 'extracted PEM' );

    ok( $decoded->csrRequest eq $extder, 'extracted DER' );

    isnt( $decoded, undef, 'load PEM from variable' ) or BAIL_OUT( Crypt::PKCS10->error );

    #is( $decoded->pkAlgorithm, 'RSA encryption', 'correct encryption algorithm' );
    is( $decoded->pkAlgorithm, 'rsaEncryption', 'encryption algorithm' );

    #is( $decoded->signatureAlgorithm, 'SHA-256 with RSA encryption', 'correct signature algorithm' );
    is( $decoded->signatureAlgorithm, 'sha256WithRSAEncryption', 'signature algorithm' );

    is( $decoded->signatureParams, undef, 'signature parameters' ); # RSA is NULL

    is( $decoded->signature(2), undef, 'signature decoding' );

  SKIP: {
        skip( "Crypt::PK::RSA not installed", 1 ) unless( eval { require Crypt::PK::RSA; } );

        ok( $decoded->checkSignature, 'verify RSA CSR signature' );
    }

    my $file = File::Spec->catpath( @dirpath, 'csr1.pem' );

    $decoded = Crypt::PKCS10->new( $file, readFile => 1, verifySignature => 0 );

    isnt( $decoded, undef, 'load PEM from filename' ) or BAIL_OUT( Crypt::PKCS10->error );

    my $der = $decoded->csrRequest;

    $file = File::Spec->catpath( @dirpath, 'csr1.cer' ); # N.B. Padding added to test removal

    if( open( my $csr, '<', $file ) ) {
	$decoded = Crypt::PKCS10->new( $csr, { verifySignature => 0, acceptPEM => 0, binaryMode => 1 }, escapeStrings => 0 );
    } else {
	BAIL_OUT( "$file: $!\n" );
    }

    isnt( $decoded, undef, 'load DER from file handle' ) or BAIL_OUT( Crypt::PKCS10->error );

    ok( $der eq $decoded->csrRequest, "DER from file matches DER from PEM" );

    subtest "subject name component access" => sub {
	plan tests => 9;

	is( join( ',',  $decoded->countryName ),            'AU',                       '/C' );
	is( join( ',',  $decoded->stateOrProvinceName ),    'Some-State',               '/ST' );
	is( join( ',',  $decoded->localityName ),           'my city',                  '/L' );
	is( join( ',',  $decoded->organizationName ),       'Internet Widgits Pty Ltd', '/O' );
	is( join( ',',  $decoded->organizationalUnitName ), 'Big org,Smaller org',      '/OU/OU' );
	is( join( ',',  $decoded->commonName ),             'My Name',                  '/CN' );
	is( join( ',',  $decoded->emailAddress ),           'none@no-email.com',        '/emailAddress' );
	is( join( ',',  $decoded->domainComponent ),        'domainComponent',          '/DC' );

	is_deeply( [ $decoded->subject ],
		   [
		    'countryName',
		    [
		     'AU'
		    ],
		    'stateOrProvinceName',
		    [
		     'Some-State'
		    ],
		    'localityName',

t/02_base.t  view on Meta::CPAN

9tEF1Lm3u9U8cmTZAvUNO9A1NlPX8e660ra6WQN2IKfDZp4XX5qisg3tus7WTfG7
aLNx7HGTQt7c2f7AlhuoQJZsCpGrcxIFmsY3yB/bTw==
-----END CERTIFICATE REQUEST-----
GOOD
    cmp_ok( $bad->csrRequest(1), 'eq', $good, 'correct invalid base64' );
};

subtest 'attribute functions' => sub {
    plan tests => 7;

    is_deeply( [ $decoded->attributes ], [qw/challengePassword unstructuredName/],
	       'attributes list is correct' );
    is( scalar $decoded->attributes( 'missing' ), undef, 'missing attribute ' );
    is( scalar $decoded->attributes( '1.2.840.113549.1.9.7' ), 'Secret',
	'challengePassword string by OID' );
    is( scalar $decoded->attributes( 'challengePassword' ), 'Secret',
	'challengePassword string' );
    is_deeply( [ $decoded->attributes( 'challengePassword' ) ], [ 'Secret' ],
	       'challengePassword array' );

    is( scalar $decoded->attributes( 'unstructuredName' ), 'MyCoFoCo',
	'unstructuredName string' );
    is_deeply( [ $decoded->attributes( 'unstructuredName' ) ], [ 'MyCoFoCo' ],
	       'unstructuredName array' );
};

subtest "basic extension functions" => sub {
    plan tests => 18;

    is_deeply( [ $decoded->extensions ],
	       [ qw/basicConstraints keyUsage extKeyUsage subjectAltName
                    subjectKeyIdentifier certificatePolicies/ ],
	       'extensions list is correct' );

    is( $decoded->extensionPresent( '-- I surely dont exist-' ), undef, 'extensionPresent undef' );
    is( $decoded->extensionPresent( '2.5.29.14' ), 1, 'extensionPresent by OID' ); # subjectKeyIdentifier
    is( $decoded->extensionPresent( 'basicConstraints' ), 2, 'extension present critical ' );

    is( $decoded->extensionValue( 'basicConstraints', 1 ), 'CA:TRUE',
	'basicConstraints string' );
    is( $decoded->extensionValue( '2.5.29.19', 1 ), 'CA:TRUE',
	'basicConstraints string by OID' );
    is_deeply( $decoded->extensionValue( 'basicConstraints' ), { CA => 'TRUE' },
	       'basicConstraints hash' );


    is( $decoded->extensionValue( 'keyUsage', 1 ),
	    'keyEncipherment,nonRepudiation,digitalSignature', 'keyUsage string' );
    ok( ref $decoded->extensionValue('KeyUsage') eq 'ARRAY', 'KeyUsage is an arrayref' );

    is_deeply( $decoded->extensionValue( 'keyUsage'), [
                                                       'keyEncipherment',
                                                       'nonRepudiation',
                                                       'digitalSignature',
                                                      ], 'keyUsage array' );

    is( $decoded->extensionValue( 'extKeyUsage', 1 ),
'emailProtection,serverAuth,clientAuth,codeSigning,emailProtection,timeStamping,OCSPSigning',
        'extKeyUsage string' );
    is_deeply( $decoded->extensionValue( 'extKeyUsage'), [
                                                          'emailProtection',
                                                          'serverAuth',
                                                          'clientAuth',
                                                          'codeSigning',
                                                          'emailProtection',
                                                          'timeStamping',
                                                          'OCSPSigning',
                                                         ], 'extKeyUsage array' );

    is( $decoded->extensionValue( 'subjectKeyIdentifier', 1 ), '0012459a',
        'subjectKeyIdentifier string' );

    is( $decoded->extensionValue( 'certificatePolicies', 1 ),
'(policyIdentifier=postOfficeBox,policyQualifier=((policyQualifierId=CPS,qualifier=http://there.example.net),'.
'(policyQualifierId=CPS,qualifier=http://here.example.net),(policyQualifierId=userNotice,'.
'qualifier=(explicitText="Trust but verify",userNotice=(noticeNumbers=(8,11),organization="Suspicious minds"))),'.
'(policyQualifierId=userNotice,qualifier=(explicitText="Trust but verify",userNotice=(noticeNumbers=(8,11),'.
'organization="Suspicious minds"))))),policyIdentifier=1.5.88.103',
        'certificatePolicies string' );
    is_deeply( $decoded->extensionValue( 'certificatePolicies' ),
            [
	     {
	      'policyIdentifier' => 'postOfficeBox',
	      'policyQualifier' => [
				    {
				     'policyQualifierId' => 'CPS',
				     'qualifier' => 'http://there.example.net'
				    },
				    {
				     'policyQualifierId' => 'CPS',

t/02_base.t  view on Meta::CPAN

						    }
				    }
				   ]
	     },
	     {
	      'policyIdentifier' => '1.5.88.103'
	     }
	    ],
		   'certificatePolicies array' );

    is( $decoded->certificateTemplate, undef, 'certificateTemplate absent' );

    is( $decoded->extensionValue('foo'), undef, 'extensionValue when extension absent' );

    is( $decoded->extensionValue('subjectAltName', 1),
        'rfc822Name=noway@none.com,uniformResourceIdentifier=htt' .
        'ps://fred.example.net,rfc822Name=someday@nowhere.exampl' .
        'e.com,dNSName=www.example.net,dNSName=www.example.com,d' .
        'NSName=example.net,dNSName=example.com,iPAddress=10.2.3' .
        '.4,iPAddress=2001:0DB8:0741:0000:0000:0000:0000:0000', 'subjectAltName' );
};

subtest "subjectAltname" => sub {
    plan tests => 5;

    my $altname = $decoded->extensionValue('subjectAltName');

    my $correct =  [
		    {
		     'rfc822Name' => 'noway@none.com'
		    },
		    {
		     'uniformResourceIdentifier' => 'https://fred.example.net'
		    },
		    {
		     'rfc822Name' => 'someday@nowhere.example.com'

t/02_base.t  view on Meta::CPAN

		    },
		    {
		     'iPAddress' => '10.2.3.4'
		    },
		    {
		     'iPAddress' => '2001:0DB8:0741:0000:0000:0000:0000:0000'
		    }
		   ];
    is_deeply( $correct, $altname, 'structure returned as extension' );

    is( $decoded->subjectAltName, 'rfc822Name:noway@none.com,' .
	'uniformResourceIdentifier:https://fred.example.net,rfc822Name:someday@nowhere.example.com,' .
	'dNSName:www.example.net,dNSName:www.example.com,dNSName:example.net,dNSName:example.com,' .
	'iPAddress:10.2.3.4,iPAddress:2001:0DB8:0741:0000:0000:0000:0000:0000',
	"subjectAltName returns string in scalar context" );

    is( join( ',', sort $decoded->subjectAltName ), 'dNSName,iPAddress,rfc822Name,uniformResourceIdentifier',
	'component list' );

    is( join( ',', $decoded->subjectAltName( 'iPAddress' )),
	'10.2.3.4,2001:0DB8:0741:0000:0000:0000:0000:0000', 'IP address list selection' );

    is( $decoded->subjectAltName( 'iPAddress' ), '10.2.3.4', 'extraction of first IP address' );
};

subtest 'oid mapping' => sub {
    plan tests => 6;

    is( Crypt::PKCS10->name2oid( 'houseIdentifier' ), '2.5.4.51', 'name2oid main table' );
    is( Crypt::PKCS10->name2oid( 'timeStamping' ), '1.3.6.1.5.5.7.3.8', 'name2oid extKeyUsages' );
    is( Crypt::PKCS10->name2oid( '-- I surely dont exist-' ), undef, 'name2oid returns undef if unknown' );

    is( Crypt::PKCS10->oid2name( '2.5.4.51' ), 'houseIdentifier', 'oid2name main table' );

t/02_base.t  view on Meta::CPAN

    plan tests => 14;

    ok( !Crypt::PKCS10->registerOID( '1.3.6.1.4.1.25043.0' ), 'OID is not registered' );
    ok( Crypt::PKCS10->registerOID( '2.5.4.51' ), 'OID is registered' );
    ok( Crypt::PKCS10->registerOID( '1.3.6.1.5.5.7.3.1' ), 'KeyUsage OID registered' );
    ok( Crypt::PKCS10->registerOID( '1.3.6.1.4.1.25043.0', 'SampleOID' ), 'Register longform OID' );
    is( Crypt::PKCS10->name2oid( 'SampleOID' ),  '1.3.6.1.4.1.25043.0', 'Find by name' );
    is( Crypt::PKCS10->oid2name( '1.3.6.1.4.1.25043.0' ), 'SampleOID', 'Find by OID' );

    ok( Crypt::PKCS10->registerOID( '1.2.840.113549.1.9.1', undef, 'e' ), 'Register /E for emailAddress' );
    cmp_ok( scalar $decoded->subject, 'eq', '/C=AU/ST=Some-State/L=my city/O=Internet Widgits Pty Ltd/OU=Big org/OU=Smaller org/CN=My Name/E=none@no-email.com/DC=domainComponent', 'Short name for /emailAddress' );

    eval{ Crypt::PKCS10->registerOID( '2.5.4.6',  undef, 'C' ) };
    like( $@, qr/^C already registered/, 'Register duplicate shortname' );

    eval{ Crypt::PKCS10->registerOID( 'A',  'name' ) };
    like( $@, qr/^Invalid OID A/, 'Register invalid OID' );

    eval{ Crypt::PKCS10->registerOID( '2.5.4.6',  'emailAddress', 'C' ) };
    like( $@, qr/^2.5.4.6 already registered/, 'Register duplicate oid' );

t/02_base.t  view on Meta::CPAN

    eval{ Crypt::PKCS10->registerOID( undef ) };
    like( $@, qr/^Not enough arguments/, 'Minimum arguments' );
};

subtest 'Microsoft extensions' => sub {
    plan tests => 10;

    my $file = File::Spec->catpath( @dirpath, 'csr2.pem' );

    if( open( my $csr, '<', $file ) ) {
	$decoded = Crypt::PKCS10->new( $csr, escapeStrings => 1, verifySignature => 0 );
    } else {
	BAIL_OUT( "$file: $!\n" );
    }

    isnt( $decoded, undef, 'load PEM from file handle' ) or BAIL_OUT( Crypt::PKCS10->error );

    is( scalar $decoded->subject, '/O=TestOrg/CN=TestCN', 'subject' );
    is_deeply( [ $decoded->attributes ],
	       [
		'ClientInformation',
		'ENROLLMENT_CSP_PROVIDER',
		'ENROLLMENT_NAME_VALUE_PAIR',
		'OS_Version'
	       ], 'attributes list' );

    is( scalar $decoded->attributes( 'ENROLLMENT_CSP_PROVIDER' ),
	'cspName="Microsoft Strong Cryptographic Provider",keySpec=2,signature=("",0)',
	'ENROLLMENT_CSP_PROVIDER string ' );
    is_deeply( $decoded->attributes( 'ENROLLMENT_CSP_PROVIDER' ),
	       {
		'cspName' => 'Microsoft Strong Cryptographic Provider',
		'keySpec' => 2,
		'signature' => [
				'',
				0
			       ]
	       }, 'ENROLLMENT_CSP_PROVIDER hash' );

    is( scalar $decoded->attributes('ENROLLMENT_NAME_VALUE_PAIR'),
	'name=CertificateTemplate,value=User', 'ENROLLMENT_NAME_VALUE_PAIR string' );
    is_deeply( $decoded->attributes('ENROLLMENT_NAME_VALUE_PAIR'),
	       {
		'name' => 'CertificateTemplate',
		'value' => 'User'
	       }, 'ENROLLMENT_NAME_VALUE_PAIR hash' );

    is( scalar $decoded->attributes('ClientInformation'),
	'MachineName=Scream,ProcessName=certreq,UserName="Scream\\\\timothe",clientId=9',
	'ClientInformation string' );
    is_deeply( $decoded->attributes('ClientInformation'),
	       {
		'MachineName' => 'Scream',
		'ProcessName' => 'certreq',
		'UserName' => 'Scream\\timothe',
		'clientId' => 9
	       }, 'ClientInformation hash' );

    is( scalar $decoded->attributes( 'OS_Version' ), '6.1.7601.2', 'OS_Version' );
};

subtest 'stringify object' => sub {
    plan tests => 9;

    my $string = eval {
	local $SIG{__WARN__} = sub { die $_[0] };

	return "$decoded";
    };

    cmp_ok( $@, 'eq', '', 'no exception' );

    isnt( $string, undef, 'returns something' );

    cmp_ok( length $string, '>=', 2800, 'approximate result length' ) or
      diag( sprintf( "actual length %u, value:\n%s\n", length $string, $string ) );

    # Perl 5.8.8 bug 39185: sometimes modifiers outside a qr don't work, but do when cloistered.

t/02_base.t  view on Meta::CPAN

    like( $string, qr'(?ms:^publicExponent\s*: 10001)', 'string includes RSA public key' );
    like( $string, qr'(?ms:^-----BEGIN PUBLIC KEY-----$)', 'string includes public key PEM' );
    like( $string, qr'(?ms:^-----END PUBLIC KEY-----$)', 'string closes public key PEM' );
    like( $string, qr'(?ms:^-----BEGIN CERTIFICATE REQUEST-----$)', 'string includes CSR PEM' );
    like( $string, qr'(?ms:^-----END CERTIFICATE REQUEST-----$)', 'string closes CSR PEM' );
};

subtest 'DSA requests' => sub {
    plan tests => 5;

    $decoded = Crypt::PKCS10->new( File::Spec->catpath( @dirpath, 'csr5.pem' ),
                                   verifySignature => 0,
                                   readFile =>1, escapeStrings => 1 );

    isnt( $decoded, undef, 'load PEM from filename' ) or BAIL_OUT( Crypt::PKCS10->error );

    is( $decoded->signatureAlgorithm, 'dsaWithSha256', 'DSA signature' );

    is_deeply( $decoded->subjectPublicKeyParams,
               {keytype => 'DSA',
                keylen => 1024,
                Q => 'b2a130635bfe19dbb3e49d8f5c4bae8266126019',
                P => 'eb3ac7a7928f0a2ab9ef61288cfde11c13e932d3853803daeb2559e8a91abc9dc48577195a471026ef27741f24e60d93a42506f16cd8bd5aebdbf519b5baa3e6470484c3c3790ffc9b5617fbd38545cd07ff60da7846383c848f0ab447ac7ed5dcd35132d882e03269f3694330d41292d92e...
                G => 'd2a82fb32f303aab7c554c91096d233cd3e87b2c9e202172a5206c7a228a39195504fcf6266748ea1a212cef6b9632bdc2012a766875c93334f7dacc24fef6ed11c185af502b236637bfdb3f8fab1de2b4bc26b45d5bb6171b8c169eca77977b5b4b9c9ca7df4052c7717bd885db9436d098...
               }, 'subjectPublicKeyParams(DSA)' );

    is( $decoded->signature(2), undef, 'signature decoding' );
  SKIP: {
        skip( "Crypt::PK::DSA is not installed", 1 ) unless( eval { require Crypt::PK::DSA; } );

        ok( $decoded->checkSignature, "verify DSA signature" );
    }
};

subtest 'PSS Padding' => sub {
    plan tests => 16;

    foreach my $file ('csr9.pem','csr9a.pem','csr9b.pem','csr9c.pem') {
        $decoded = Crypt::PKCS10->new( File::Spec->catpath( @dirpath, $file ),
                        verifySignature => 0,
                        readFile =>1, escapeStrings => 1 );

        isnt( $decoded, undef, 'load PEM from filename' ) or BAIL_OUT( Crypt::PKCS10->error );

        is( $decoded->signatureAlgorithm, 'rsassaPss', 'RSA_PSS signature' );

        is( $decoded->signature(2), undef, 'signature decoding' );
        SKIP: {
            skip( "Crypt::PK::RSA is not installed", 1 ) unless( eval { require Crypt::PK::RSA; } );
            ok( $decoded->checkSignature, "verify RSA PSS signature" );
        }
    }
};

subtest 'API v0' => sub {
    plan tests => 6;

    Crypt::PKCS10->setAPIversion( 0 );
    my $csr = eval { Crypt::PKCS10->new( '', PEMonly => 1 ); };
    is( $csr, undef, 'new is undef' );

t/03_ecc.t  view on Meta::CPAN


plan tests => 24;

pass( 'configuration' );
diag( sprintf( "Perl %s version %vd\n", $^X, $^V ) );

ok( Crypt::PKCS10->setAPIversion(1), 'setAPIversion 1' );

my @dirpath = (File::Spec->splitpath( $0 ))[0,1];

my $decoded;
$decoded = Crypt::PKCS10->new( File::Spec->catpath( @dirpath, 'csr4.pem' ),
                               readFile => 1, escapeStrings => 1, PEMonly => 1 );

isnt( $decoded, undef, 'load PEM from file' ) or BAIL_OUT( Crypt::PKCS10->error );

is( scalar $decoded->subject, '/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd', 'subject' );

is( $decoded->commonName, "", 'CSR commonName' );

is( $decoded->subjectPublicKey, '048d0507a7ebf58a17910fe2b15b0c451e93bc948a4bafb7bf1204d6043e7de1394230befab9c5115cd3cd1e059a545788bb1e0830ee06300c4f3e8d87128f3ddc', 'hex subjectPublicKey' );

is( $decoded->subjectPublicKey(1), << '_KEYPEM_', 'PEM subjectPublicKey' );
-----BEGIN PUBLIC KEY-----
MFowFAYHKoZIzj0CAQYJKyQDAwIIAQEHA0IABI0FB6fr9YoXkQ/isVsMRR6TvJSK
S6+3vxIE1gQ+feE5QjC++rnFEVzTzR4FmlRXiLseCDDuBjAMTz6NhxKPPdw=
-----END PUBLIC KEY-----
_KEYPEM_

is( $decoded->signature, '30440220730d25ebe5f187c607577cc106d3141dc7f90827914f2a6a11ebc9de6fdf1d26022042c02e4819f2c16c56181205c6c2176902f20cbfcfdc1fa82b30f79bd15d2172',
    'signature' );

is( scalar $decoded->subject, '/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd',
    'subject()' );

is( $decoded->pkAlgorithm, 'ecPublicKey', 'encryption algorithm' );

is_deeply( $decoded->subjectPublicKeyParams,
           {keytype => 'ECC',
            keylen => 256,
            curve => 'brainpoolP256r1',
            'pub_x' => '8D0507A7EBF58A17910FE2B15B0C451E93BC948A4BAFB7BF1204D6043E7DE139',
            'pub_y' => '4230BEFAB9C5115CD3CD1E059A545788BB1E0830EE06300C4F3E8D87128F3DDC',
           }, 'subjectPublicKeyParams(EC brainpool)' );

is( $decoded->signatureAlgorithm, 'ecdsa-with-SHA256', 'signature algorithm' );

my $sig = $decoded->signature( 2 );
ok( defined $sig &&
    substr( $sig->{r}->as_hex, 2 ) eq '730d25ebe5f187c607577cc106d3141dc7f90827914f2a6a11ebc9de6fdf1d26' &&
    substr( $sig->{s}->as_hex, 2 ) eq '42c02e4819f2c16c56181205c6c2176902f20cbfcfdc1fa82b30f79bd15d2172',
    'ECDSA signature components' );


my $key = $decoded->subjectPublicKey(1);

isnt( $key = Crypt::PK::ECC->new( \$key ), undef, 'parse EC key' );
# Seems curve_name can be reported in UPPERcase with old version of
# Crypt::PK::ECC.  curve_oid can also be missing...
my $kh = $key->key2hash;
if( $kh->{curve_name} =~ /^BRAINPOOLP256R1$/ || !exists $kh->{curve_oid}) {
    BAIL_OUT( "Crypt::PK::ECC version is too old" );
}
my $keyh = {
   'curve_A' => '7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9',

t/03_ecc.t  view on Meta::CPAN

   'curve_order' => 'A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7',
   'curve_prime' => 'A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377',
   'k' => '',
   'pub_x' => '8D0507A7EBF58A17910FE2B15B0C451E93BC948A4BAFB7BF1204D6043E7DE139',
   'pub_y' => '4230BEFAB9C5115CD3CD1E059A545788BB1E0830EE06300C4F3E8D87128F3DDC',
   'size' => 32,
   'type' => 0,
           };
is_deeply( $kh, $keyh, 'extract EC parameters' );

is_deeply( $decoded->subjectPublicKeyParams(1), {
   'curve' => 'brainpoolP256r1',
   'detail' => $keyh,
   'keylen' => 256,
   'keytype' => 'ECC',
   'pub_x' => '8D0507A7EBF58A17910FE2B15B0C451E93BC948A4BAFB7BF1204D6043E7DE139',
   'pub_y' => '4230BEFAB9C5115CD3CD1E059A545788BB1E0830EE06300C4F3E8D87128F3DDC',
                                                }, 'detailed EC parameters' );


$decoded = Crypt::PKCS10->new( File::Spec->catpath( @dirpath, 'csr6.pem' ),
                               readFile => 1, PEMonly => 1, escapeStrings => 1 );

isnt( $decoded, undef, 'load PEM from file' ) or BAIL_OUT( Crypt::PKCS10->error );

is( $decoded->pkAlgorithm, 'ecPublicKey', 'encryption algorithm' );

is_deeply( $decoded->subjectPublicKeyParams,
           {keytype => 'ECC',
            keylen => 384,
            curve => 'secp384r1',
            'pub_x' => '43FCD15809728171AECA3029A002C13424E92F5D39C3FB7074B5B4B8802FA3E9AB79E1F6CC174596AA09C6BEA9DFAAFF',
            'pub_y' => '1891F7048842DF14F3FDCABB81C40BDDBFDA64A20FCEA13136DF8109AB56D205F857A295ED00C6B7FAFB6240D66447EB',
           }, 'subjectPublicKeyParams(EC secp)' );

is( $decoded->signatureAlgorithm, 'ecdsa-with-SHA384', 'signature algorithm' );

$decoded = Crypt::PKCS10->new( File::Spec->catpath( @dirpath, 'csr7.pem' ),
                               readFile => 1, PEMonly => 1, escapeStrings => 1 );

is( $decoded, undef, 'bad signature rejected' ) or BAIL_OUT( Crypt::PKCS10->error );

$decoded = Crypt::PKCS10->new( File::Spec->catpath( @dirpath, 'csr7.pem' ),
                               readFile => 1, PEMonly => 1, escapeStrings => 1, verifySignature => 0 );

isnt( $decoded, undef, 'bad signature loaded' ) or BAIL_OUT( Crypt::PKCS10->error );

ok( !$decoded->checkSignature, 'checkSignature returns false' );
ok( defined Crypt::PKCS10->error, 'checkSignature sets error string' );



( run in 0.297 second using v1.01-cache-2.11-cpan-26ccb49234f )