1# -*- mode: cperl; -*- 2 3# Elliptic curve CSR tests 4# 5# This software is copyright (c) 2014 by Gideon Knocke. 6# Copyright (c) 2016 Gideon Knocke, Timothe Litt 7# 8# This is free software; you can redistribute it and/or modify it under 9# the same terms as the Perl 5 programming language system itself. 10# 11# Terms of the Perl programming language system itself 12# 13# a) the GNU General Public License as published by the Free 14# Software Foundation; either version 1, or (at your option) any 15# later version, or 16# b) the "Artistic License" 17# 18# See LICENSE for details. 19# 20use strict; 21use warnings; 22 23use Test::More 0.94; 24 25use File::Spec; 26use Crypt::PKCS10; 27 28unless( eval { require Crypt::PK::ECC; } ) { 29 plan skip_all => "Crypt::PK::ECC is not installed, skipping ECC tests"; 30} 31 32plan tests => 24; 33 34pass( 'configuration' ); 35diag( sprintf( "Perl %s version %vd\n", $^X, $^V ) ); 36 37ok( Crypt::PKCS10->setAPIversion(1), 'setAPIversion 1' ); 38 39my @dirpath = (File::Spec->splitpath( $0 ))[0,1]; 40 41my $decoded; 42$decoded = Crypt::PKCS10->new( File::Spec->catpath( @dirpath, 'csr4.pem' ), 43 readFile => 1, escapeStrings => 1, PEMonly => 1 ); 44 45isnt( $decoded, undef, 'load PEM from file' ) or BAIL_OUT( Crypt::PKCS10->error ); 46 47is( scalar $decoded->subject, '/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd', 'subject' ); 48 49is( $decoded->commonName, "", 'CSR commonName' ); 50 51is( $decoded->subjectPublicKey, '048d0507a7ebf58a17910fe2b15b0c451e93bc948a4bafb7bf1204d6043e7de1394230befab9c5115cd3cd1e059a545788bb1e0830ee06300c4f3e8d87128f3ddc', 'hex subjectPublicKey' ); 52 53is( $decoded->subjectPublicKey(1), << '_KEYPEM_', 'PEM subjectPublicKey' ); 54-----BEGIN PUBLIC KEY----- 55MFowFAYHKoZIzj0CAQYJKyQDAwIIAQEHA0IABI0FB6fr9YoXkQ/isVsMRR6TvJSK 56S6+3vxIE1gQ+feE5QjC++rnFEVzTzR4FmlRXiLseCDDuBjAMTz6NhxKPPdw= 57-----END PUBLIC KEY----- 58_KEYPEM_ 59 60is( $decoded->signature, '30440220730d25ebe5f187c607577cc106d3141dc7f90827914f2a6a11ebc9de6fdf1d26022042c02e4819f2c16c56181205c6c2176902f20cbfcfdc1fa82b30f79bd15d2172', 61 'signature' ); 62 63is( scalar $decoded->subject, '/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd', 64 'subject()' ); 65 66is( $decoded->pkAlgorithm, 'ecPublicKey', 'encryption algorithm' ); 67 68is_deeply( $decoded->subjectPublicKeyParams, 69 {keytype => 'ECC', 70 keylen => 256, 71 curve => 'brainpoolP256r1', 72 'pub_x' => '8D0507A7EBF58A17910FE2B15B0C451E93BC948A4BAFB7BF1204D6043E7DE139', 73 'pub_y' => '4230BEFAB9C5115CD3CD1E059A545788BB1E0830EE06300C4F3E8D87128F3DDC', 74 }, 'subjectPublicKeyParams(EC brainpool)' ); 75 76is( $decoded->signatureAlgorithm, 'ecdsa-with-SHA256', 'signature algorithm' ); 77 78my $sig = $decoded->signature( 2 ); 79ok( defined $sig && 80 substr( $sig->{r}->as_hex, 2 ) eq '730d25ebe5f187c607577cc106d3141dc7f90827914f2a6a11ebc9de6fdf1d26' && 81 substr( $sig->{s}->as_hex, 2 ) eq '42c02e4819f2c16c56181205c6c2176902f20cbfcfdc1fa82b30f79bd15d2172', 82 'ECDSA signature components' ); 83 84 85my $key = $decoded->subjectPublicKey(1); 86 87isnt( $key = Crypt::PK::ECC->new( \$key ), undef, 'parse EC key' ); 88# Seems curve_name can be reported in UPPERcase with old version of 89# Crypt::PK::ECC. curve_oid can also be missing... 90my $kh = $key->key2hash; 91if( $kh->{curve_name} =~ /^BRAINPOOLP256R1$/ || !exists $kh->{curve_oid}) { 92 BAIL_OUT( "Crypt::PK::ECC version is too old" ); 93} 94my $keyh = { 95 'curve_A' => '7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9', 96 'curve_B' => '26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6', 97 'curve_Gx' => '8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262', 98 'curve_Gy' => '547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997', 99 'curve_bits' => 256, 100 'curve_bytes' => 32, 101 'curve_cofactor' => 1, 102 'curve_name' => 'brainpoolp256r1', 103 'curve_oid' => '1.3.36.3.3.2.8.1.1.7', 104 'curve_order' => 'A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7', 105 'curve_prime' => 'A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377', 106 'k' => '', 107 'pub_x' => '8D0507A7EBF58A17910FE2B15B0C451E93BC948A4BAFB7BF1204D6043E7DE139', 108 'pub_y' => '4230BEFAB9C5115CD3CD1E059A545788BB1E0830EE06300C4F3E8D87128F3DDC', 109 'size' => 32, 110 'type' => 0, 111 }; 112is_deeply( $kh, $keyh, 'extract EC parameters' ); 113 114is_deeply( $decoded->subjectPublicKeyParams(1), { 115 'curve' => 'brainpoolP256r1', 116 'detail' => $keyh, 117 'keylen' => 256, 118 'keytype' => 'ECC', 119 'pub_x' => '8D0507A7EBF58A17910FE2B15B0C451E93BC948A4BAFB7BF1204D6043E7DE139', 120 'pub_y' => '4230BEFAB9C5115CD3CD1E059A545788BB1E0830EE06300C4F3E8D87128F3DDC', 121 }, 'detailed EC parameters' ); 122 123 124$decoded = Crypt::PKCS10->new( File::Spec->catpath( @dirpath, 'csr6.pem' ), 125 readFile => 1, PEMonly => 1, escapeStrings => 1 ); 126 127isnt( $decoded, undef, 'load PEM from file' ) or BAIL_OUT( Crypt::PKCS10->error ); 128 129is( $decoded->pkAlgorithm, 'ecPublicKey', 'encryption algorithm' ); 130 131is_deeply( $decoded->subjectPublicKeyParams, 132 {keytype => 'ECC', 133 keylen => 384, 134 curve => 'secp384r1', 135 'pub_x' => '43FCD15809728171AECA3029A002C13424E92F5D39C3FB7074B5B4B8802FA3E9AB79E1F6CC174596AA09C6BEA9DFAAFF', 136 'pub_y' => '1891F7048842DF14F3FDCABB81C40BDDBFDA64A20FCEA13136DF8109AB56D205F857A295ED00C6B7FAFB6240D66447EB', 137 }, 'subjectPublicKeyParams(EC secp)' ); 138 139is( $decoded->signatureAlgorithm, 'ecdsa-with-SHA384', 'signature algorithm' ); 140 141$decoded = Crypt::PKCS10->new( File::Spec->catpath( @dirpath, 'csr7.pem' ), 142 readFile => 1, PEMonly => 1, escapeStrings => 1 ); 143 144is( $decoded, undef, 'bad signature rejected' ) or BAIL_OUT( Crypt::PKCS10->error ); 145 146$decoded = Crypt::PKCS10->new( File::Spec->catpath( @dirpath, 'csr7.pem' ), 147 readFile => 1, PEMonly => 1, escapeStrings => 1, verifySignature => 0 ); 148 149isnt( $decoded, undef, 'bad signature loaded' ) or BAIL_OUT( Crypt::PKCS10->error ); 150 151ok( !$decoded->checkSignature, 'checkSignature returns false' ); 152ok( defined Crypt::PKCS10->error, 'checkSignature sets error string' ); 153 154