我的另一个问题..
总的来说,我一直在尝试定义authenticate_alexa/1
。
这个(我认为)提供了与amazon这个java代码相同的功能:https://github.com/amzn/alexa-skills-kit-java/blob/master/src/com/amazon/speech/speechlet/authentication/SpeechletRequestSignatureVerifier.java
有关此操作的说明,请访问:https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/developing-an-alexa-skill-as-a-web-service
我现在面临的问题是,我需要阅读完整的httpsbody请求并找到其哈希值,以便验证它是否与我们获得的链中的密钥一起工作。(验证签名的步骤7)。
所以我需要定义httpsbody/2
来完全返回正文,然后使用正确的代码来验证哈希值。
我目前的代码是:
alexa(Request):-
authenticate_alexa(Request),
%http_read_json_dict(Request,DictIn),
%handle_dict(DictIn,DictOut),
my_json_answer(hello,DictOut),
reply_json(DictOut).
authenticate_alexa(Request):-
check_sigchainurl(Request,URL),
portray_clause(user_error,URL),
get_certs(URL,[ACert|CertsRest]),
checkcertvalid_time(ACert),
checkchain([ACert|CertsRest]),
memberchk(key(Key),ACert),
base64decodesig_encryptedSig(Request,ESig),
% httpsbody(Request,Body), %how do we read the body of the request?
httpsbodybytes(Request,Body),
portray_clause(user_error,'Http Body from httpsbody(Request,Body) :'),
portray_clause(user_error,Body),
crypto_data_hash(Body,Hash,[algorithm(sha1),encoding(octet)]),
portray_clause(user_error,'Serviced signed Hash:'),
portray_clause(user_error,Hash),
atom_string(Hash,HashString),
string_concat("0x",HashString,HashString2),
number_string(HashNumber,HashString2),
portray_clause(user_error,'Hash as Dec'),
portray_clause(user_error,HashNumber),
signature_pow(ESig,0x010001,Key,ClpfdHash),
portray_clause(user_error,'clpfdhash:'),
portray_clause(user_error,ClpfdHash),
%rsa_verify(Key,Hash,ESig,[type(sha1)]),
portray_clause(user_error,done).
get_certs(URL,Certs):-
setup_call_cleanup(
http_open(URL,Stream,[]),
ssl_peer_certificate_chain(Stream,Certs),
close(Stream)
).
signature_pow(Sig, Exp, P, Pow) :-
portray_clause(user_error,'ESig:'),
portray_clause(user_error,Sig),
(atom(Sig) -> portray_clause(user_error,'it is an atom');portray_clause(user_error,'it is not an atom')),
(number(Sig) -> portray_clause(user_error,'it is a number');portray_clause(user_error,'it is not a number')),
atom_string(Sig,Sigstring),
string_concat("0x",Sigstring,SigString2),
number_string(SigNumber,SigString2),
portray_clause(user_error,'Exp:'),
portray_clause(user_error,Exp),
portray_clause(user_error,'P:'),
portray_clause(user_error,P),
P =public_key(rsa(P2,EXP2,_,_,_,_,_,_)),
portray_clause(user_error,'P just number:'),
portray_clause(user_error,P2),
(string(P2) -> portray_clause(user_error,'String hex P number');portray_clause(user_error,notstring)),
string_concat("0x",P2,NewString),
portray_clause(user_error,NewString),
number_string(P3,NewString),
portray_clause(user_error,'P number as dec:'),
portray_clause(user_error,P3),
Pow #= SigNumber^Exp mod P3,
portray_clause(user_error,'Pow'),
portray_clause(user_error,Pow),
portray_clause(user_error,verified).
check_sigchainurl(Request,URL):-
memberchk(signaturecertchainurl(URL),Request),
parse_url(URL,P), %what about normalise url? I dont think it is needed
memberchk(protocol(https),P),%should make case insenstive
memberchk(host('s3.amazonaws.com'),P), %should make case insenstive
memberchk(path(Path),P),
string_concat('/echo.api/',_,Path),
(memberchk(port(Port),P) -> Port =443 ; true).
checkcertvalid_time(Acert):-
memberchk(notbefore(NotBefore),Acert),
memberchk(notafter(NotAfter),Acert),
get_time(NowA),
Now is round(NowA),
Now #>NotBefore,
Now #<NotAfter.
checkchain(Chain):-
length(Chain,L),
L#>1. %Insure chain has more than one cert
%portray_clause(user_error,Chain),
checkchain_h(Chain).
checkchain_h([_]). %Reached the root.
checkchain_h(Chain):-
Chain =[C1,C2|Rest],
memberchk(signature(Sig),C1),
memberchk(to_be_signed(Signed),C1),
memberchk(key(Key),C2),
hex_bytes(Signed,Bytes),
crypto_data_hash(Bytes,Hash,[algorithm(sha256),encoding(octet)]),
rsa_verify(Key,Hash,Sig,[type(sha256)]),
checkchain_h([C2|Rest]).
base64decodesig_encryptedSig(Request,Hex):-
memberchk(signature(B64Sig),Request),
portray_clause(user_error,'base64 encoded sig:'),
portray_clause(user_error,B64Sig),
base64(ESig,B64Sig),
atom_codes(ESig,Bytes),
hex_bytes(Hex,Bytes).
%portray_clause(user_error,'Esig is base64 sig decoded using base64//2:'),
%portray_clause(user_error,ESig).
%portray_clause(user_error,'Can not print esig').
httpsbodybytes(Request,BodyBytes2):-
memberchk(input(In),Request),
portray_clause(user_error,"Bytes:"),
mygetbody2(In,BodyBytes,0),
list_butlast(BodyBytes,BodyBytes2).
mygetbody2(_Stream,[],-1).
mygetbody2(Stream,[Byte|Bytes],Check):-
dif(Check,-1),
get_byte(Stream,Byte),
%portray_clause(user_error,Byte),
mygetbody2(Stream,Bytes,Byte).
list_butlast([X|Xs], Ys) :- % use auxiliary predicate ...
list_butlast_prev(Xs, Ys, X). % ... which lags behind by one item
list_butlast_prev([], [], _).
list_butlast_prev([X1|Xs], [X0|Ys], X0) :-
list_butlast_prev(Xs, Ys, X1).
收到请求时输出:
'https://s3.amazonaws.com/echo.api/echo-api-cert-4.pem'.
'base64 encoded sig:'.
'Nu2v3C8hWNSF7G7N/B5WWqFnhuGMPJeMGi76FanbF8D4so+AiRSWVaehPXoaiLZpCiEb5Ysd+QFCBEt5/5a6MoLh4JTAhwGcnGUs+GbZo7rkk12t6meUTldnBNZ4/1boUNGurWCmPy1pkCWyHIt7udWj2zCdHx+4cFCKy8GVWfjOtZ3n52LWzGd+HO0RF0GQ25cSoFQGr2I5bT060Bodt3PrZob/nWnPxqayC+y53Itt/I0YUtM2QnPYByx/GJuyzMUuA0/v0PH15oGOE+wwYszr1C6mmEKMRdkCzFEO6z4kuw6UeXDaECS9ak04XCp+gsYkHQjJYpoB3s8T6qeNGQ=='.
"Bytes:".
'Http Body from httpsbody(Request,Body) :'.
[123, 34, 118, 101, 114, 115, 105, 111, 110, 34, 58, 34, 49, 46, 48, 34, 44, 34, 115, 101, 115, 115, 105, 111, 110, 34, 58, 123, 34, 110, 101, 119, 34, 58, 102, 97, 108, 115, 101, 44, 34, 115, 101, 115, 115, 105, 111, 110, 73, 100, 34, 58, 34, 83, 101, 115, 115, 105, 111, 110, 73, 100, 46, 99, 55, 99, 54, 49, 55, 51, 100, 45, 98, 98, 102, 52, 45, 52, 56, 57, 101, 45, 97, 48, 98, 97, 45, 52, 54, 55, 102, 101, 56, 48, 51, 100, 97, 101, 99, 34, 44, 34, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 34, 58, 123, 34, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 73, 100, 34, 58, 34, 97, 109, 122, 110, 49, 46, 97, 115, 107, 46, 115, 107, 105, 108, 108, 46, 97, 50, 55, 101, 98, 53, 48, 53, 45, 102, 99, 101, 102, 45, 52, 57, 98, 102, 45, 56, 57, 55, 53, 45, 51, 101, 49, 97, 54, 100, 55, 98, 55, 99, 55, 52, 34, 125, 44, 34, 97, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 58, 123, 125, 44, 34, 117, 115, 101, 114, 34, 58, 123, 34, 117, 115, 101, 114, 73, 100, 34, 58, 34, 97, 109, 122, 110, 49, 46, 97, 115, 107, 46, 97, 99, 99, 111, 117, 110, 116, 46, 65, 71, 77, 77, 80, 53, 85, 81, 73, 81, 80, 89, 52, 69, 75, 90, 90, 72, 88, 71, 68, 52, 86, 72, 55, 89, 72, 80, 55, 88, 65, 51, 54, 84, 65, 79, 50, 82, 54, 76, 87, 79, 77, 89, 73, 88, 75, 78, 52, 68, 72, 88, 88, 51, 66, 73, 83, 53, 87, 83, 82, 78, 84, 53, 65, 55, 86, 79, 75, 86, 82, 76, 50, 77, 75, 65, 78, 77, 86, 51, 75, 50, 68, 77, 79, 66, 50, 87, 75, 85, 68, 84, 72, 73, 74, 86, 87, 73, 77, 83, 65, 51, 76, 81, 75, 82, 73, 73, 83, 72, 71, 55, 80, 71, 55, 77, 89, 70, 65, 53, 50, 72, 77, 73, 67, 81, 87, 53, 53, 76, 50, 73, 90, 65, 76, 70, 90, 80, 77, 82, 54, 67, 74, 83, 74, 54, 74, 55, 90, 82, 75, 54, 54, 77, 87, 82, 55, 66, 89, 88, 69, 76, 66, 73, 50, 75, 79, 69, 90, 81, 73, 72, 68, 88, 79, 72, 72, 90, 70, 71, 90, 50, 81, 83, 90, 82, 87, 52, 75, 55, 79, 55, 53, 82, 50, 89, 88, 74, 54, 85, 87, 65, 86, 70, 77, 53, 65, 34, 125, 125, 44, 34, 114, 101, 113, 117, 101, 115, 116, 34, 58, 123, 34, 116, 121, 112, 101, 34, 58, 34, 73, 110, 116, 101, 110, 116, 82, 101, 113, 117, 101, 115, 116, 34, 44, 34, 114, 101, 113, 117, 101, 115, 116, 73, 100, 34, 58, 34, 69, 100, 119, 82, 101, 113, 117, 101, 115, 116, 73, 100, 46, 101, 54, 98, 56, 102, 101, 101, 100, 45, 101, 99, 101, 51, 45, 52, 101, 97, 97, 45, 97, 102, 50, 100, 45, 99, 52, 55, 102, 54, 53, 55, 53, 57, 50, 49, 54, 34, 44, 34, 116, 105, 109, 101, 115, 116, 97, 109, 112, 34, 58, 34, 50, 48, 49, 55, 45, 48, 54, 45, 49, 57, 84, 48, 57, 58, 52, 54, 58, 51, 53, 90, 34, 44, 34, 108, 111, 99, 97, 108, 101, 34, 58, 34, 101, 110, 45, 71, 66, 34, 44, 34, 105, 110, 116, 101, 110, 116, 34, 58, 123, 34, 110, 97, 109, 101, 34, 58, 34, 103, 101, 116, 65, 78, 101, 119, 70, 97, 99, 116, 34, 125, 125, 125].
'Serviced signed Hash:'.
'64f1329a1f707809174ee50a6df9f65099bba371'.
'Hash as Dec'.
576277964734800966164187927075551858658582963057.
'ESig:'.
'36edafdc2f2158d485ec6ecdfc1e565aa16786e18c3c978c1a2efa15a9db17c0f8b28f8089149655a7a13d7a1a88b6690a211be58b1df90142044b79ff96ba3282e1e094c087019c9c652cf866d9a3bae4935dadea67944e576704d678ff56e850d1aead60a63f2d699025b21c8b7bb9d5a3db309d1f1fb870508acbc19559f8ceb59de7e762d6cc677e1ced11174190db9712a05406af62396d3d3ad01a1db773eb6686ff9d69cfc6a6b20becb9dc8b6dfc8d1852d3364273d8072c7f189bb2ccc52e034fefd0f1f5e6818e13ec3062ccebd42ea698428c45d902cc510eeb3e24bb0e947970da1024bd6a4d385c2a7e82c6241d08c9629a01decf13eaa78d19'.
'it is an atom'.
'it is not a number'.
'Exp:'.
65537.
'String hex P number'.
'P number as dec:'.
23367091749731801702903258951332579149824717752403036738901918995576378221876991769215986117060832205938888292020670601919717320529579897428555756633750717630113812467159229456710215094841206836055184753491046351652384568208399197333334554354625485949013821994244854426626217946383766717620084958916568639573896625634280251135248126961353512501885364402868885624724204807768627558428281558589460261611023934365963620820837651899784648073096603839587883308136461448176498481934437054583664797923342609641294880521414948881981392762983173267396409953920339084175033120756130451537931813023420728016059287928243275252817.
'Pow'.
12996685404671854237337597057543403676067050401691031855263389356566563793267812208256044577937494803172529297811694697178075070962940655950099948830185429064594023055861430145065585159411714852185690089480769442404348006975883315459440182824265725834630838968686976962484449232569444592352993640898180649431183234665232203068528805991370779087967630073792656438871568328046165107095895856647485355472888016164031315511155737623289424119686691313121050647697592969024984185347837785283636035540443593041046047481149874499335289745021686457982828945403796990195913021023926745047308779421759663632404133499645864797253.
verified.
'clpfdhash:'.
12996685404671854237337597057543403676067050401691031855263389356566563793267812208256044577937494803172529297811694697178075070962940655950099948830185429064594023055861430145065585159411714852185690089480769442404348006975883315459440182824265725834630838968686976962484449232569444592352993640898180649431183234665232203068528805991370779087967630073792656438871568328046165107095895856647485355472888016164031315511155737623289424119686691313121050647697592969024984185347837785283636035540443593041046047481149874499335289745021686457982828945403796990195913021023926745047308779421759663632404133499645864797253.
done.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
两个哈希值不相同。所以它目前无法正常工作。
答案 0 :(得分:2)
暂定答案:
我认为你与read_string/3
走在正确的轨道上,但是你需要将其分解为一个更易于管理的案例,以便其他人有机会提供帮助。例如,请添加到您的问题:
我已经解释了如何获取签名的哈希:
https://stackoverflow.com/a/44524628/1613573
请参阅基于CLP(FD)的计算。
请注意,在建立连接时(通过TLS),这纯粹是 HTTP (非HTTPS)层的问题。
有用的谓词:
我看到你也正在努力解决实际的Base64编码签名问题。要理解这一点,您可以应用以下步骤:
base64/2
获取普通原子,即base64(Plain, Encoded)
atom_codes/2
获取代表原子的代码列表,即atom_codes(Plain, Bytes)
library(crypto)
中的hex_bytes/2
获取签名的十六进制编码,即hex_bytes(Hex, Bytes)
。因此,您可以使用签名的可用十六进制表示获得。您可以使用此进行进一步计算,使用CLP(FD)约束或rsa_verify/4
。
我在您的示例中尝试过这些计算,我得到一个以Pow #= Sig^Exp mod M
结尾的整数:
b2feb64cd1ae11365f8917b71bb751142b63f159e12c02a1720b78958c3e7f7e
以十六进制表示法。这是不您计算的哈希值。因此,您可能会使用编码来计算自己的数据哈希以验证签名。请参阅crypto_data_hash/3
的值。特别是,我建议crypto_data_hash(Bytes, Hash, [encoding(bytes)])
,您必须确保Bytes
是表示传输数据的实际字节列表。