Ace:IMSPython: Difference between revisions
From Adapt
No edit summary |
No edit summary |
||
(One intermediate revision by the same user not shown) | |||
Line 6: | Line 6: | ||
=Request One Token= | =Request One Token= | ||
The ACE IMS provides a requestTokensImmediate call which can be used to request tokens for a supplied set of hash values. The tokens returned from this call can be used to validate the hash of any file hasn't been modified. | |||
===Code=== | ===Code=== | ||
<pre> | <pre> | ||
Line 20: | Line 23: | ||
</pre> | </pre> | ||
The resulting token contains the name you supplied in the request, a proof for the hash value you submitted, and importantly the round ID and digest algorithm used to calculate the proof. You will use the round, digest algorithm and proof to later validate a file's hash value. | |||
* digestService - digest algorithm used to build proof | |||
* name - descriptive name you supplied in the request | |||
* proofElements - proof hashes used to validate file | |||
* roundID - which round were these tokens part of, used to validate proof result | |||
The other items are also returned, but are not necessary to validate a proof | |||
* statusCode - 100 if success, some other number otherwise (see source code) | |||
* timestamp - exact time of token generation, useful, but should not be trusted as its not linked to the proof | |||
* tokenClassName - internal queue used to generate this queue, useful for debugging only | |||
===Output=== | ===Output=== | ||
<pre> | <pre> | ||
Line 55: | Line 69: | ||
</pre> | </pre> | ||
= | =Generate a token for a file= | ||
Using hashlib, and binascii we can use python to both generate a digest and grab an ace token for that digest. | Using hashlib, and binascii we can use python to both generate a digest and grab an ace token for that digest. | ||
While this example only sends one request in a call, you should batch your requests prior to requesting a token. Just send a 'list' of tokenRequest objects to requestTokensImmediate. The IMS will support up to 10,000 requests per call. | |||
===Code=== | ===Code=== | ||
<pre> | <pre> | ||
Line 119: | Line 136: | ||
</pre> | </pre> | ||
=Round Requests= | |||
In order to validate the proof for any file, you need to recompute the proof result and compare that to the round hash stored on the IMS. The getRoundSummaries should be used to request the hash for previously generated rounds. | |||
You can find the id for the round you need to retrieve in the roundId field in an ace token. | |||
===Code=== | ===Code=== | ||
<pre> | <pre> |
Latest revision as of 21:03, 7 January 2011
Using the python suds library it's fairly trivial to request tokens from the ACE IMS service.
- https://fedorahosted.org/suds/ - suds library, examples written for version 0.4
Validating ace tokens is described in on the ims overview page and token store example page
Request One Token
The ACE IMS provides a requestTokensImmediate call which can be used to request tokens for a supplied set of hash values. The tokens returned from this call can be used to validate the hash of any file hasn't been modified.
Code
from suds.client import Client url='http://ims.umiacs.umd.edu:8080/ace-ims/IMSWebService?wsdl' client = Client(url) request = client.factory.create('tokenRequest') request.hashValue = '4ed9ba3d9c7e3e092d0b0e3441f04574' request.name = 'MyFile' result = client.service.requestTokensImmediate('SHA-256-0',reqlist) print result
The resulting token contains the name you supplied in the request, a proof for the hash value you submitted, and importantly the round ID and digest algorithm used to calculate the proof. You will use the round, digest algorithm and proof to later validate a file's hash value.
- digestService - digest algorithm used to build proof
- name - descriptive name you supplied in the request
- proofElements - proof hashes used to validate file
- roundID - which round were these tokens part of, used to validate proof result
The other items are also returned, but are not necessary to validate a proof
- statusCode - 100 if success, some other number otherwise (see source code)
- timestamp - exact time of token generation, useful, but should not be trusted as its not linked to the proof
- tokenClassName - internal queue used to generate this queue, useful for debugging only
Output
[python] [toaster@loach ace-cli]$ python test2.py [(tokenResponse){ digestService = "SHA-256" name = "somename" proofElements[] = (proofElement){ hashes[] = "9129f93bc8ac2d93e35aa6206298fb8616690211a8563db51cf2ea1159682692", index = 0 }, (proofElement){ hashes[] = "34bd07cc18a7ab1a47467081dcb21a6ca1857b1d3bdc12106ba2fd538b3bafbd", index = 0 }, (proofElement){ hashes[] = "8a2042da9a114a41cf3738a841d65336af5b864ed6be8484c6bae4a4ac9e65a1", index = 0 }, (proofElement){ hashes[] = "e95826668c3f301bef729e60157bbd3dbc346859ceee71655a9a065106276d72", index = 1 }, roundId = 2892850 statusCode = 100 timestamp = 2011-01-07 12:59:36.000013 tokenClassName = "SHA-256-0" }]
Generate a token for a file
Using hashlib, and binascii we can use python to both generate a digest and grab an ace token for that digest.
While this example only sends one request in a call, you should batch your requests prior to requesting a token. Just send a 'list' of tokenRequest objects to requestTokensImmediate. The IMS will support up to 10,000 requests per call.
Code
import hashlib import binascii from suds.client import Client filename='test2.py' digFile = open(filename,'rb') hashAlg = hashlib.sha256() hashAlg.update(digFile.read()) filedigest = binascii.b2a_hex(hashAlg.digest()) url='http://ims.umiacs.umd.edu:8080/ace-ims/IMSWebService?wsdl' client = Client(url) print filename, ' ', filedigest request = client.factory.create('tokenRequest') request.hashValue = filedigest request.name = filename result = client.service.requestTokensImmediate('SHA-256-0',request) print result
Output
[python] [toaster@loach ace-cli]$ python test2.py test2.py 164182eef9792e2e1c5005cd9240ff508aef042b8fa344597431eae39370c784 [(tokenResponse){ digestService = "SHA-256" name = "test2.py" proofElements[] = (proofElement){ hashes[] = "c5e82872eeee3dfa539202a9757f8a5364b6fded4dfcb40b66084158f2b5c627", index = 0 }, (proofElement){ hashes[] = "6e16a71847403f4e586625463160993bfab189c0bba771d81354c03d9c3591fd", index = 0 }, (proofElement){ hashes[] = "0879b385c366d07142446a18dfb6d19c468a733991e9685fc75ce6f4b929b659", index = 0 }, (proofElement){ hashes[] = "e19dd18bd9eabf79a074d72231a7117bd2319a859d31a429575b4657e85d0c95", index = 1 }, roundId = 2893078 statusCode = 100 timestamp = 2011-01-07 13:08:27.000253 tokenClassName = "SHA-256-0" }]
Round Requests
In order to validate the proof for any file, you need to recompute the proof result and compare that to the round hash stored on the IMS. The getRoundSummaries should be used to request the hash for previously generated rounds.
You can find the id for the round you need to retrieve in the roundId field in an ace token.
Code
from suds.client import Client url='http://ims.umiacs.umd.edu:8080/ace-ims/IMSWebService?wsdl' client = Client(url) result = client.service.getRoundSummaries(2893078) print result[0].id print result[0].hashValue
Output
[python] [toaster@loach ace-cli]$ python test2.py 2893078 1324d496da42e04347c74001f8bd948b31fa296419ee49246ba5494970b16752
Complete Example, file to round
This example will read a file, compute its digest and request a token. It will then recompute the round hash using the
Code
import hashlib import binascii from suds.client import Client filename='test2.py' digFile = open(filename,'rb') hashAlg = hashlib.sha256() hashAlg.update(digFile.read()) binarydigest = hashAlg.digest() filedigest = binascii.b2a_hex(binarydigest) url='http://ims.umiacs.umd.edu:8080/ace-ims/IMSWebService?wsdl' client = Client(url) print '---File to secure:' print filename, ' ', filedigest print '\n---Token Response from IMS' request = client.factory.create('tokenRequest') request.hashValue = filedigest request.name = filename token = client.service.requestTokensImmediate('SHA-256-0',request) print 'Round:', token[0].roundId, ' Date:', token[0].timestamp print token[0].proofElements print '\n---Computing proof' level = 0 prevhash = binarydigest for element in token[0].proofElements: i = 0 hashAlg = hashlib.sha256() # create level by converting hashes to bytes and inserting # previous level where necessary, first level uses file hash for strhash in element.hashes: if i == element.index: hashAlg.update(prevhash) hashAlg.update(binascii.a2b_hex(strhash)) i = i + 1 # in case previous level is to be inserted at end if i == element.index: hashAlg.update(prevhash) prevhash = hashAlg.digest() print 'Level:',level, '( index:',element.index,') ', binascii.b2a_hex(prevhash) level = level + 1 print '\n---Requesting Round Hash for',token[0].roundId rounds = client.service.getRoundSummaries(token[0].roundId) print 'Round hash:', rounds[0].hashValue print '\n---Comparing Round Hash to computed proof hash' print rounds[0].hashValue print binascii.b2a_hex(prevhash) print 'Equal:',binascii.b2a_hex(prevhash) == rounds[0].hashValue
Output
[python] [toaster@loach ace-cli]$ python test2.py ---File to secure: test2.py 1f9bf12fc4e402d6cad8b36f9f6e0482af14add1b00f0f5aff2197309483a199 ---Token Response from IMS Round: 2895642 Date: 2011-01-07 14:54:21.000883 [(proofElement){ hashes[] = "31ed6c99ea3932bd2cbc8db0e42fc7bd028a773ac7e2359785f55fe076a6492b", index = 0 }, (proofElement){ hashes[] = "be071a2271d0be7633e986c4463cbc3fc39e244d75948000c41583e78d0398e3", index = 0 }, (proofElement){ hashes[] = "2cb53579297ff25fa6492e6f9b4cc130acf379f1061e31d2e5fd65da734c0f91", index = 0 }, (proofElement){ hashes[] = "439e40fbeae4635d014091ed93324cd467c61a3848516ee99d2c0bb20e02e7cf", index = 1 }] ---Computing proof Level: 0 ( index: 0 ) f91649510d117b361d6023b8846f12f273de0e25fab257d94be774a77bd222c6 Level: 1 ( index: 0 ) 1d56960d990765a1581559786df5e77dbdcf25e6c53b79f215375001ac761f88 Level: 2 ( index: 0 ) 31473c279b3d0d4714b096fe59c0aaa2b36286cbf3e82dbc9afb73a988a33f3e Level: 3 ( index: 1 ) 1ccba7f2302c71615f20e5b5768a118fbf44781e40bd2d7e5479ddd11a46d44c ---Requesting Round Hash for 2895642 Round hash: 1ccba7f2302c71615f20e5b5768a118fbf44781e40bd2d7e5479ddd11a46d44c ---Comparing Round Hash to computed proof hash 1ccba7f2302c71615f20e5b5768a118fbf44781e40bd2d7e5479ddd11a46d44c 1ccba7f2302c71615f20e5b5768a118fbf44781e40bd2d7e5479ddd11a46d44c Equal: True
Challenge Round Data
The above example shows how to assert a digest you have hasn't been tampered with. Now, how much do you trust the IMS? Using an external witness value, you can challenge the IMS to provide a proof for any round to that day's witness value. Checking the proof for a witness identical to checking an individual file except you start with the round as your base and end up with a witness instead of starting at a file's digest and ending with a round.
There is a caveat, as the witness is only generated once a day, you will have to wait until the next day after a witness has been created to run a challenge.
The createWitnessProofForRound call will generate a proof which links that round to the daily witness value. These calls take a little bit of time to run since the IMS will compute this proof on demand for you.
Code
import hashlib import binascii from suds.client import Client # # Witness value retrieved from: # http://groups.google.com/group/ace-ims-witness # roundid = 2855147 trustedwitnessvalue='d85e36d6af2246d76c9a4fa0ef22eb10a5215eae5747504241b92b18f2c22467' url='http://ims.umiacs.umd.edu:8080/ace-ims/IMSWebService?wsdl' client = Client(url) print '\n---Requesting Round Hash for',roundid rounds = client.service.getRoundSummaries(roundid) print 'Round hash:', rounds[0].hashValue print '\n---Requesting proof to witness for round',roundid witnessProof = client.service.createWitnessProofForRound(roundid) print 'Witness ID:', witnessProof[0].witnessId, 'Timestamp:',witnessProof[0].roundTimestamp, witnessProof[0].tokenClassName, witnessProof[0].digestService print witnessProof[0].proofElements print '\n---Calculating round to witness proof',roundid level = 0 prevhash = binascii.a2b_hex(rounds[0].hashValue) for element in witnessProof[0].proofElements: i = 0 hashAlg = hashlib.sha256() # create level by converting hashes to bytes and inserting # previous level where necessary, first level uses file hash for strhash in element.hashes: if i == element.index: hashAlg.update(prevhash) hashAlg.update(binascii.a2b_hex(strhash)) i = i + 1 # in case previous level is to be inserted at end if i == element.index: hashAlg.update(prevhash) prevhash = hashAlg.digest() print 'Level:',level, '( index:',element.index,') ', binascii.b2a_hex(prevhash) level = level + 1 imswitnessvalue = binascii.b2a_hex(prevhash) print '\n---Comparing trusted value to IMS proof result' print 'calculated',imswitnessvalue print 'trusted ',trustedwitnessvalue print 'Equal:',imswitnessvalue == trustedwitnessvalue
Output
[python] [toaster@loach ace-cli]$ python test3.py ---Requesting Round Hash for 2855147 Round hash: 476106066c46a15f96be17327c7054fdf3c87821db73ff88daeb4ca83f53cb57 ---Requesting proof to witness for round 2855147 Witness ID: 1759 Timestamp: 2011-01-06 07:00:54 SHA-256 SHA-256 [(proofElement){ hashes[] = "1671688d58c4d8e99f373db6d3796a21fc127e3f987b13cf76e589bf12c1123e", "d1ec79775ae3ba83a3f856500867a15881094d3cb316363d98beaf32c3703227", index = 2 }, (proofElement){ hashes[] = "ddca1a9842a99566159a9f7d37f023017c54a641f1b08812037629aea33413f6", "eb7248c5a7f7dfbb02a5275a17207acf3246a43bb10cce2b89dfae7a2f45b6c1", index = 0 }, (proofElement){ hashes[] = "7ab730b239cf7090f8780623831e4e4630262560228238dbec9f10b7ace5c6de", "b48bb4a7d92c7fe235e5e3c621ef92ccb6f9a62d7f85b65c4a460d042770daf4", index = 0 }, (proofElement){ hashes[] = "5d2aa0ebc2169fd8b4f9f2776e2dec9bd2d6a2e169a38102e5ae865870db117b", index = 0 }, (proofElement){ hashes[] = "10790984f6a92b6f174a361f2aad4fc8fb0c04da3e61153dafc3618ab157c169", "948293675f27d4936f3ed22e8e0796438354db7b2b846eec91b330a8b197cd6f", index = 0 }, (proofElement){ hashes[] = "68cff51aec86801f471d97175531463a42a89d12109f7d75c11094d53ec64103", "8a18326494ebee7c157c16e5ab0fcc1fbf072557a21a409b576d04e6c1658f07", index = 0 }, (proofElement){ hashes[] = "6d63317567c24842e9e3d44c31adf00178417a62706ac7cf22e1d4ce9b533a3a", index = 0 }, (proofElement){ hashes[] = "dfe600269076511a438f0cbe9a01f9aa953995f00b763ba8f77fd812215493cb", "8cc299dd7b44ec61bb88281913cb765fb4bbdfabac6e1fd150b81ba85fa42ba0", index = 0 }, (proofElement){ hashes[] = "f989203eeb71a2eb0b4695ecc0c68844eb81b77adcb0fb996f31d43c0241172d", "caf20c717052f249caa3cbb31edc3ad0dd89f67cefdce390ff87abcd6ec38fc8", index = 0 }, (proofElement){ hashes[] = "8bffee5e9d2ff42c58eafcce8f58f0177ce7c8ca87523e1e050f21d521463036", "5ec4c85c0ebaf1f05fd75dc23553782d489187bca2717565c7594e03f254a959", index = 0 }, (proofElement){ hashes[] = "b3bf6e304d5854100d5308eca1fe249e90ca22df43ad8ce63b863bdcd8eecdd8", "2118cc520d42975cec0883a15ac8821e4122b3c92128c6c3455fe925f7f4d398", index = 0 }, (proofElement){ hashes[] = "774fe5a3e1baee2c4ed07a3f6bc5b4634b4959a9f9f5fc52743d2ebd50eed453", "058cb6172362b4081ac7ee80c2fb49c65afe97aa7f4f0740f68128201899b2d8", index = 0 }, (proofElement){ hashes[] = "a53a90c997334f7b42a418d46df3c9f66957ad649d11250ca306f7baaa50a62c", index = 0 }, (proofElement){ hashes[] = "3b6e1c9a642c22cbd902bc3a5acfdc31537ee00669bb707ea6065a378741ac1f", index = 0 }, (proofElement){ hashes[] = "cdf23c541a7196d3eceb609d85f897990a5c111bc05f87eb45854bcaf3611b4f", index = 1 }] ---Calculating round to witness proof 2855147 Level: 0 ( index: 2 ) fab1ec8cf671971f6c0814bebcc293f706d50bed8ef943cdb16e0f4f1286070c Level: 1 ( index: 0 ) 054a29efa2926be0c192020b1fb21879b63f51f77bc5760db8a3f66d1d5079af Level: 2 ( index: 0 ) e8de10ebb57a3b7737fce745098e9e2556fa4e843984cfbdc9348f9cfa51127a Level: 3 ( index: 0 ) bf3fb03228aaf5585ca056b24c2582ba91e2e012823e7f0bb0f6b1feab14b65c Level: 4 ( index: 0 ) c885cba7f7e01c9d1db515d8b949201fcfbea164789075aef6ec1bbf5cf8fb04 Level: 5 ( index: 0 ) f6367c8e4fc62deb1fc43448c71062fde34f563820df713d26514a4550d2576b Level: 6 ( index: 0 ) baedb56e2afdf0565736078d739c9cb1fb609ed0bf8d9846a1a190a3f971ca8e Level: 7 ( index: 0 ) 4c35406d87d7cb495cb08527d5900811a7e5c0a287d795c570d7f8515e9c9958 Level: 8 ( index: 0 ) b7f4d6813489f6ee45b058466595db24d443bfb331082e7363e7ccd42f76970d Level: 9 ( index: 0 ) f74dfcfea8e8b3f1394eaf4e8c5e455add53a8907b7f1f9113067a042661fd0b Level: 10 ( index: 0 ) b12da578de58bd6150c37a865de23d881de4bf56ba010d0f8d20e5b70dc82656 Level: 11 ( index: 0 ) 9d3b4d729a0036232e2121c24d7ea5211f30536de22d792c4f64256173149ea4 Level: 12 ( index: 0 ) 6e00cd2d65d663f4686c7ec7046b362adcda70139ce7a6d164163affc50598d1 Level: 13 ( index: 0 ) 296cee71935d5f925cb04a31b67c6dc12d91f0fc6d413af0f9fc313311f494f3 Level: 14 ( index: 1 ) d85e36d6af2246d76c9a4fa0ef22eb10a5215eae5747504241b92b18f2c22467 ---Comparing trusted value to IMS proof result calculated d85e36d6af2246d76c9a4fa0ef22eb10a5215eae5747504241b92b18f2c22467 trusted d85e36d6af2246d76c9a4fa0ef22eb10a5215eae5747504241b92b18f2c22467 Equal: True