[erlang-questions] ECC public key example

Ben Hood 0x6e6562@REDACTED
Sat Jul 27 17:31:22 CEST 2013


Hey Gustav,

Just in case anybody googles this and needs a quick solution, I've put
a working example onto Github: https://github.com/0x6e6562/otp_ecc

Cheers,

Ben

On Sat, Jul 27, 2013 at 3:39 PM, Ben Hood <0x6e6562@REDACTED> wrote:
> 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