Как использовать Elliptic Curves Diffie-Hellman с SJCL в JS и OpenSSL в Ruby
Используя Elliptic-Curves Diffie-Hellman, я хочу подключить SLCL - JS (документация) на клиенте и OpenSSL - Ruby (документация) на сервере.
Я нашел подобный вопрос здесь, но он не был должным образом ответил, и это также не то, что я действительно ищу, так как он использует sjcl.ecc.elGamal.generateKeys(384, 10)
в то время как я надеюсь использовать sjcl.ecc.curves['c384']
<- NIST
Тем не менее, я все еще использовал и модифицировал его код для тестирования, потому что у меня были проблемы с использованием sjcl.ecc.curves['c384']
создание единого открытого ключа, и это то, что я придумал.
//Javascript
keypair = sjcl.ecc.elGamal.generateKeys(384, 10);
console.log(keypair.pub._point.toBits()); //Changed from his serialize()
Это приводит к
[-1992414123, 638637875, 1917312913, 73389700, -425224557, 743777818, 970253455, 723842951, -1751664279, 982132367, -1949786746, 1067402923, -869929568, 157928816, 1651634060, 1968161300, -216192372, -1858642177, -1345910998, -2128793177, -1325754797, 143080818, 1868787479, -484135391]
Используя вывод в ruby:
#Ruby
pointArr = [-1992414123, 638637875, 1917312913, 73389700, -425224557, 743777818, 970253455, 723842951, -1751664279, 982132367, -1949786746, 1067402923, -869929568, 157928816, 1651634060, 1968161300, -216192372, -1858642177, -1345910998, -2128793177, -1325754797, 143080818, 1868787479, -484135391]
# ugly bit magic to somehow convert the above array into a proper byte array (in form of a string)
pointStr = [(pointArr.map { |i| (i>=0)?('0'*(8-i.to_s(16).length)+i.to_s(16)):("%08X" % (2**32-1+i+1)) }*'').upcase].pack("H*")
#My modified code
pointInt = pointStr.unpack('B*').first.to_i(2) #Convert BitStr to integer
pointBN = OpenSSL::BN.new(pointInt.to_s, 10) #Int to BigNumber (to be used as param below)
group = OpenSSL::PKey::EC::Group.new('secp384r1') #EC Group to be used
client_pub_point = OpenSSL::PKey::EC::Point.new(group, pointBN)
# ^
# ^ ABOVE'S MY PROBLEM -> OpenSSL::PKey::EC::Point::Error: invalid encoding
# ^
#Server EC: code taken and modified from https://www.ruby-forum.com/topic/3966195
ec = OpenSSL::PKey::EC.new(group)
ec.generate_key
pub = OpenSSL::PKey::EC.new(group)
pub.public_key = client_pub_point
#Compute Shared Key
shared_key = ec.dh_compute_key(pub.public_key)
puts shared_key.unpack('I>*')
Это "помещает" что-то вроде ниже, когда используется оригинальный код из [(ссылка)] ( https://www.ruby-forum.com/topic/3966195) выше
3747233514
2683763564
475565567
1087119841
857380668
2490387914
3548975947
2348082236
2093543365
1477205987
4289120093
3330807042
Это должно быть, но на всякий случай вот мой тест
irb(main):113:0> ec = OpenSSL::PKey::EC.new(group)
=> #<OpenSSL::PKey::EC:0x37f4250>
irb(main):114:0> ec.generate_key
=> #<OpenSSL::PKey::EC:0x37f4250>
irb(main):115:0> pub = OpenSSL::PKey::EC.new(group)
=> #<OpenSSL::PKey::EC:0x374f070>
irb(main):116:0> pub.public_key = ec.public_key
=> #<OpenSSL::PKey::EC::Point:0x37f8090>
irb(main):117:0> pub.public_key.to_bn
=> 7699789176960498967958014210931326569901199635665512831714857096185925821659134057981449113945854620725216613989823482205311316333140754760317456176281271361802541262755346331375041208726203461213190230560617504850860621520632944763
irb(main):119:0> OpenSSL::PKey::EC::Point.new(group, pub.public_key.to_bn)
=> #<OpenSSL::PKey::EC:0x4029f48>
#The ABOVE FORMAT works, unlike the error I got like the following
irb(main):122:0> pointBN
=> 832312614609895991150696681555479456971598284480953722479085426901428295415600048953528780331647571635767075686130334170313461289491500162782258792834115040597490936949579748064005380309022482780162833924377801386781542770068991521
irb(main):123:0> OpenSSL::PKey::EC::Point.new(group, pointBN)
OpenSSL::PKey::EC::Point::Error: invalid encoding
Но сравнивая работающее и нерабочее чуть выше, кажется, что общее количество десятичных цифр одинаково, так что я думаю, что я в некотором роде на правильном пути, но я просто не мог понять это.
Для тех, кто может столкнуться с такой проблемой, это мои справочные коды (1) (2) (3) (4) (5)
Я застрял на этом два дня и, похоже, об этом мало что пишут в сети, и я не смог найти другую библиотеку JS, которая поддерживает эллиптическую кривую. Любая помощь приветствуется.
2 ответа
Я наконец-то решил эту проблему!:)
Я использовал другую библиотеку Javascript. Если вы ищете решение подобной проблемы, как это, пожалуйста, обратитесь к другому моему вопросу (ссылка)
# Сервер EC: код взят и изменен с https://www.ruby-forum.com/topic/3966195 ec = OpenSSL:: PKey:: EC.new (группа) ec.generate_key ...
Обычно мы просто звоним EC_KEY_new_by_curve_name
с NID хорошо известной кривой. NID будет включать в себя:
NID_secp160k1
NID_secp192k1
NID_secp224k1
NID_secp256k1
NID_secp384r1
NID_secp521r1
- другие кривые первичного поля
- другие кривые бинарного поля
Я думаю, что полный их список доступен в источниках OpenSSL, obj_mac.h
:
#define SN_secp112r1 "secp112r1"
#define NID_secp112r1 704
#define OBJ_secp112r1 OBJ_secg_ellipticCurve,6L
#define SN_secp112r2 "secp112r2"
#define NID_secp112r2 705
#define OBJ_secp112r2 OBJ_secg_ellipticCurve,7L
#define SN_secp128r1 "secp128r1"
#define NID_secp128r1 706
#define OBJ_secp128r1 OBJ_secg_ellipticCurve,28L
#define SN_secp128r2 "secp128r2"
#define NID_secp128r2 707
#define OBJ_secp128r2 OBJ_secg_ellipticCurve,29L
#define SN_secp160k1 "secp160k1"
#define NID_secp160k1 708
#define OBJ_secp160k1 OBJ_secg_ellipticCurve,9L
#define SN_secp160r1 "secp160r1"
#define NID_secp160r1 709
#define OBJ_secp160r1 OBJ_secg_ellipticCurve,8L
#define SN_secp160r2 "secp160r2"
#define NID_secp160r2 710
#define OBJ_secp160r2 OBJ_secg_ellipticCurve,30L
#define SN_secp192k1 "secp192k1"
#define NID_secp192k1 711
#define OBJ_secp192k1 OBJ_secg_ellipticCurve,31L
#define SN_secp224k1 "secp224k1"
#define NID_secp224k1 712
#define OBJ_secp224k1 OBJ_secg_ellipticCurve,32L
#define SN_secp224r1 "secp224r1"
#define NID_secp224r1 713
#define OBJ_secp224r1 OBJ_secg_ellipticCurve,33L
#define SN_secp256k1 "secp256k1"
#define NID_secp256k1 714
#define OBJ_secp256k1 OBJ_secg_ellipticCurve,10L
#define SN_secp384r1 "secp384r1"
#define NID_secp384r1 715
#define OBJ_secp384r1 OBJ_secg_ellipticCurve,34L
#define SN_secp521r1 "secp521r1"
#define NID_secp521r1 716
#define OBJ_secp521r1 OBJ_secg_ellipticCurve,35L
#define SN_sect113r1 "sect113r1"
#define NID_sect113r1 717
#define OBJ_sect113r1 OBJ_secg_ellipticCurve,4L
#define SN_sect113r2 "sect113r2"
#define NID_sect113r2 718
#define OBJ_sect113r2 OBJ_secg_ellipticCurve,5L
#define SN_sect131r1 "sect131r1"
#define NID_sect131r1 719
#define OBJ_sect131r1 OBJ_secg_ellipticCurve,22L
#define SN_sect131r2 "sect131r2"
#define NID_sect131r2 720
#define OBJ_sect131r2 OBJ_secg_ellipticCurve,23L
#define SN_sect163k1 "sect163k1"
#define NID_sect163k1 721
#define OBJ_sect163k1 OBJ_secg_ellipticCurve,1L
#define SN_sect163r1 "sect163r1"
#define NID_sect163r1 722
#define OBJ_sect163r1 OBJ_secg_ellipticCurve,2L
#define SN_sect163r2 "sect163r2"
#define NID_sect163r2 723
#define OBJ_sect163r2 OBJ_secg_ellipticCurve,15L
#define SN_sect193r1 "sect193r1"
#define NID_sect193r1 724
#define OBJ_sect193r1 OBJ_secg_ellipticCurve,24L
#define SN_sect193r2 "sect193r2"
#define NID_sect193r2 725
#define OBJ_sect193r2 OBJ_secg_ellipticCurve,25L
#define SN_sect233k1 "sect233k1"
#define NID_sect233k1 726
#define OBJ_sect233k1 OBJ_secg_ellipticCurve,26L
#define SN_sect233r1 "sect233r1"
#define NID_sect233r1 727
#define OBJ_sect233r1 OBJ_secg_ellipticCurve,27L
#define SN_sect239k1 "sect239k1"
#define NID_sect239k1 728
#define OBJ_sect239k1 OBJ_secg_ellipticCurve,3L
#define SN_sect283k1 "sect283k1"
#define NID_sect283k1 729
#define OBJ_sect283k1 OBJ_secg_ellipticCurve,16L
#define SN_sect283r1 "sect283r1"
#define NID_sect283r1 730
#define OBJ_sect283r1 OBJ_secg_ellipticCurve,17L
#define SN_sect409k1 "sect409k1"
#define NID_sect409k1 731
#define OBJ_sect409k1 OBJ_secg_ellipticCurve,36L
#define SN_sect409r1 "sect409r1"
#define NID_sect409r1 732
#define OBJ_sect409r1 OBJ_secg_ellipticCurve,37L
#define SN_sect571k1 "sect571k1"
#define NID_sect571k1 733
#define OBJ_sect571k1 OBJ_secg_ellipticCurve,38L
#define SN_sect571r1 "sect571r1"
#define NID_sect571r1 734
#define OBJ_sect571r1 OBJ_secg_ellipticCurve,39L
...
#Compute Shared Key shared_key = ec.dh_compute_key (pub.public_key)
Есть пример ECDH на вики OpenSSL. Я полагаю, Мэтт Касвелл предоставил это. Вы можете найти его по эллиптической кривой Диффи-Хеллмана.
Я думаю, что пример вики OpenSSL также был скопирован / вставлен здесь однажды: секреты ECDH, генерируемые API-интерфейсом BouncyCastle и OpenSSL, различаются.
Я не знаю SJCL или Ruby, поэтому я не могу вам помочь.
sjcl.ecc.curves ['c384'] <- NIST
Я верю, что ты захочешь NID_secp384r1
для этого, но я не знаю Руби, так что принимайте это за чистую монету. Список именованных кривых для NID см. В OpenSSL: openssl / CHANGES openssl / apps / ecparam.c openssl / crypto....
Если вы собираетесь сохранить ключ на диск и, возможно, позже использовать его в сертификате (например, подпись ECDSA), вам нужно установить OPENSSL_EC_NAMED_CURVE
флаг. Флаг просто сохраняет параметры группы по имени (например, ASN1 OID: prime256v1
) вместо перечисления всех параметров домена в объектах ASN1 (тип поля, первичное или двоичное поле, базовая точка и т. д.).
Вы делаете это с:
EC_KEY_set_asn1_flag(key, OPENSSL_EC_NAMED_CURVE);
Если вы не установите флаг, то при согласовании комплектов вы увидите ошибку "нет общих шифров". Вот симптомы на клиенте и сервере:
Клиент (s_client):
139925962778272:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:s3_pkt.c:1256:SSL alert number 40
139925962778272:error:1409E0E5:SSL routines:SSL3_WRITE_BYTES:ssl handshake failure:s3_pkt.c:596:
Сервер (s_server):
140339533272744:error:1408A0C1:SSL routines:SSL3_GET_CLIENT_HELLO:no shared cipher:s3_srvr.c:1353: