[erlang-questions] ECC public key example

Ben Hood 0x6e6562@REDACTED
Sat Jul 27 16:39:53 CEST 2013


Hi Gustav,

Thank you very much for deciphering the API for me :-)

Using your example as inspiration, I was able to sign and verify some
data with the key pair generated using openssl:

$ openssl ecparam -out ecdsa.pem -name sect571r1 -genkey
$ openssl ec -in ecdsa.pem -pubout -out ecdsa.pub

I take your point about how you pulled the ECParams out of the private
key, although this is actually necessary to construct the public key.
However, I was able to extract this out of the SPKI stanza:

#'SubjectPublicKeyInfo'{algorithm = #'AlgorithmIdentifier'{algorithm =
{1,2,840,10045,2,1},

           parameters = <<6,5,43,129,4,0,39>>},
                        subjectPublicKey = {0,

<<4,4,179,52,127,201,246,179,111,174,210,158,176,114,47,

61,131,42,95,74,96,132,1,196,...>>}},
EcpkParametersPem = {'EcpkParameters', <<6,5,43,129,4,0,39>>, not_encrypted},
ECParams = public_key:pem_entry_decode(EcpkParametersPem).

As for the issue with the OTPEcpkParameters pattern mismatch, judging
from the ASN.1 definitions for the public_key module in R16B01, I
think that the entity has somehow been prefixed with OTP by mistake.
Previously to parse the private key file I had taken the same approach
- see my original post. I too would question whether the ASN.1 schema
is correct in this regard.

Anyway, although you have to jump through a number of hoops, ECC
signature verification in Erlang is now working for me.

Thanks very much for your help.

Cheers,

Ben

On Sat, Jul 27, 2013 at 3:10 PM, Gustav Simonsson
<gustav.simonsson@REDACTED> wrote:
> Hi Ben,
>
> I've replicated your console commands (see end of mail) and continued with
> steps which end with a successful verification of the signature with the EC
> Public Key.
> Some duplicated commands is removed from the log but it should still contain
> all the necessary steps.
>
> Some things I noticed:
>
> * There is one SubjectPublicKeyInfo which contains another
> SubjectPublicKeyInfo.
>    This doesn't seem correct and I'm not really sure where the error causing
> this is.
>
> * The EC Public Key type in public_key is defined as:
>
> ec_public_key()  = {#'ECPoint'{}, #'EcpkParameters'{} | {namedCurve, oid()}}
>
> But the EC Public Key Parameters are actually returned as a
> 'OTPEcpkParameters' PEM entry (record)
> whose record definition is missing. I suspect this could be a bug in
> public_key.
>
> * I didn't find a way to get a #'ECPoint' record back from decoding, so I
> manually created it by
>    matching out the ECPoint octets from the SPKI record.
>
> * As the EC parameters was in the private key file, they had to be manually
> combined with the ECPoint
>    to form the EC Public Key. Maybe it's possible to tell openssl to include
> the EC parameters in the public
>    key file with some option?
>
> Test keys where generated with:
>
> openssl ecparam -out ec_key_priv.pem -name prime192v1 -genkey
> openssl ec -pubout -in ec_key_priv.pem -out ec_key_pub.pem
>
> Cheers,
> Gustav Simonsson
>
> Erlang console log:
> ==================
>
> Erlang R16B01 (erts-5.10.2) [source] [64-bit] [smp:4:4] [async-threads:10]
> [hipe] [kernel-poll:false]
>
> Eshell V5.10.2  (abort with ^G)
> 1> rr(public_key).
> ['AAControls','ACClearAttrs','AccessDescription',
>  'Algorithm','AlgorithmIdentifier',
>  'AlgorithmIdentifierPKCS-10','AlgorithmIdentifierPKCS-8',
>  'AlgorithmIdentifierPKCS5v2-0','AlgorithmIdentifierPKSC-7',
>  'AlgorithmNull','AnotherName','AttCertValidityPeriod',
>  'Attribute','AttributeCertificate',
>  'AttributeCertificateInfo','AttributePKCS-10',
>  'AttributePKCS-7','AttributeTypeAndValue',
>  'Attributes_SETOF',
>  'Attributes_SETOF_valuesWithContext_SETOF',
>  'AuthorityKeyIdentifier','BasicConstraints',
>  'BuiltInDomainDefinedAttribute','BuiltInStandardAttributes',
>  'Certificate','CertificateList','CertificationRequest',
>  'CertificationRequestInfo',
>  'CertificationRequestInfo_attributes_SETOF'|...]
> 2> {ok, Bin} = file:read_file("ec_key_priv.pem").
> {ok,<<"-----BEGIN EC PARAMETERS-----\nBggqhkjOPQMBAQ==\n-----END EC
> PARAMETERS-----\n-----BEGIN EC PRIVATE KEY-----\nMF"...>>}
> 3> {ok, Bin2} = file:read_file("ec_key_pub.pem").
> {ok,<<"-----BEGIN PUBLIC
> KEY-----\nMEkwEwYHKoZIzj0CAQYIKoZIzj0DAQEDMgAEUzzXw5xYnyZKIzSIo1xKN3enUe3M\nWSURKrWKOUB+Of+e"...>>}
> 4> [OTPEcpkParamsPem, ECPrivateKeyPem] = public_key:pem_decode(Bin).
> [{'OTPEcpkParameters',<<6,8,42,134,72,206,61,3,1,1>>,
>                       not_encrypted},
>  {'ECPrivateKey',<<48,95,2,1,1,4,24,233,53,27,191,96,145,
>                    18,240,229,16,151,232,48,95,167,203,176,
>                    145,...>>,
>                  not_encrypted}]
> 5> ECPrivateKey = public_key:pem_entry_decode(ECPrivateKeyPem).
> #'ECPrivateKey'{version = 1,
>                 privateKey = [233,53,27,191,96,145,18,240,229,16,151,232,48,
>                               95,167,203,176,145,117,205,108,210,242,204],
>                 parameters = {namedCurve,{1,2,840,10045,3,1,1}},
>                 publicKey = {0,
>
> <<4,83,60,215,195,156,88,159,38,74,35,52,136,163,92,
>                                74,55,119,167,81,237,204,...>>}}
> 6> {_, ParamsBin, ParamsEnc} = OTPEcpkParamsPem.
> {'OTPEcpkParameters',<<6,8,42,134,72,206,61,3,1,1>>,
>                      not_encrypted}
> 7> EcpkParametersPem = {'EcpkParameters', ParamsBin, ParamsEnc}.
> {'EcpkParameters',<<6,8,42,134,72,206,61,3,1,1>>,
>                   not_encrypted}
> 8> ECParams = public_key:pem_entry_decode(EcpkParametersPem).
> {namedCurve,{1,2,840,10045,3,1,1}}
> 9> Msg = <<"The superhamster strikes again at 7PM">>.
> <<"The superhamster strikes again at 7PM">>
> 10> Sig = public_key:sign(Msg, sha256, ECPrivateKey).
> <<48,53,2,25,0,233,72,76,239,158,251,181,114,254,166,85,
>   195,11,179,248,53,150,58,138,93,86,76,171,41,...>>
> 11> [SPKI] = public_key:pem_decode(Bin2).
> [#'SubjectPublicKeyInfo'{algorithm = <<48,73,48,19,6,7,42,
>                                        134,72,206,61,2,1,
>                                        6,8,42,134,72,206,
>                                        61,3,1,1,3,50,0,...>>,
>                          subjectPublicKey = not_encrypted}]
> 12> #'SubjectPublicKeyInfo'{algorithm = Der} = SPKI.
> #'SubjectPublicKeyInfo'{algorithm = <<48,73,48,19,6,7,42,
>                                       134,72,206,61,2,1,6,
>                                       8,42,134,72,206,61,
>                                       3,1,1,3,50,0,4,...>>,
>                         subjectPublicKey = not_encrypted}
> 14> RealSPKI = public_key:der_decode('SubjectPublicKeyInfo', Der).
> #'SubjectPublicKeyInfo'{
>     algorithm =
>         #'AlgorithmIdentifier'{
>             algorithm = {1,2,840,10045,2,1},
>             parameters = <<6,8,42,134,72,206,61,3,1,1>>},
>     subjectPublicKey =
>         {0,
>          <<4,83,60,215,195,156,88,159,38,74,35,52,136,163,92,74,
>            55,119,167,81,237,204,89,37,...>>}}
> 15> #'SubjectPublicKeyInfo'{subjectPublicKey = {_, Octets}} = RealSPKI.
> #'SubjectPublicKeyInfo'{
>     algorithm =
>         #'AlgorithmIdentifier'{
>             algorithm = {1,2,840,10045,2,1},
>             parameters = <<6,8,42,134,72,206,61,3,1,1>>},
>     subjectPublicKey =
>         {0,
>          <<4,83,60,215,195,156,88,159,38,74,35,52,136,163,92,74,
>            55,119,167,81,237,204,89,37,...>>}}
> 16> ECPoint = #'ECPoint'{point = Octets}.
> #'ECPoint'{point = <<4,83,60,215,195,156,88,159,38,74,35,
>                      52,136,163,92,74,55,119,167,81,237,
>                      204,89,37,17,42,181,...>>}
> 18> ECPublicKey = {ECPoint, ECParams}.
> {#'ECPoint'{point = <<4,83,60,215,195,156,88,159,38,74,
>                       35,52,136,163,92,74,55,119,167,81,
>                       237,204,89,37,17,42,...>>},
>  {namedCurve,{1,2,840,10045,3,1,1}}}
> 19> public_key:verify(Msg, sha256, Sig, ECPublicKey).
> true
>
> =============================
>
>
> On Fri, Jul 26, 2013 at 7:38 PM, Ben Hood <0x6e6562@REDACTED> wrote:
>>
>> Hi,
>>
>> I'd like to verify signatures signed with ec keys generated by openssl
>> in Erlang.
>>
>> Using R16B01 I've been able to convince the public_key module to sign
>> some data with an openssl generated private key thusly:
>>
>> {ok, Pem} = file:read_file("ec_private_key.pem"),
>> [ECParameters,ECPrivateKey] = public_key:pem_decode(Pem),
>> PrivateKey = public_key:pem_entry_decode(ECPrivateKey),
>> Curve = public_key:pem_entry_decode({'EcpkParameters', Params, Enc}),
>> Sig = public_key:sign(Message, sha512, PrivateKey).
>>
>> But when it comes to processing the public key, it is not entirely
>> clear how to decode it. This is where I got to:
>>
>> {ok, Pem} = file:read_file("ec_public_key.pem"),
>> [{_,Der,_}] = public_key:pem_decode(Pem),
>> {_, _, {0, KeyDer}} = public_key:der_decode('SubjectPublicKeyInfo', Der),
>> [179,52,127,201] = public_key:der_decode('ECPoint', KeyDer)
>> %% This is where the story ends
>>
>> I've looked through the ASN.1 types available and there doesn't seem
>> to be anything that resembles an ECPublicKey.
>>
>> Could anybody point me to working example?
>>
>> Cheers,
>>
>> Ben
>> _______________________________________________
>> erlang-questions mailing list
>> erlang-questions@REDACTED
>> http://erlang.org/mailman/listinfo/erlang-questions
>
>



More information about the erlang-questions mailing list