renault-api
renault-api copied to clipboard
[DO NOT MERGE] SRP POC
This new spr.py file only needs renault-api installed in the system (I tested it in WSL), so it does not depend on other files in this repository. At the top of the file there are 4 vars with user IDs, vin and pincode to fill. Sometimes I saw this flow fails earlier, but in general 90% of the time it should try to complete all the steps. The final step does shoudl show that the command was CANCELLED (because srp auth fails now) - there is no logic to check this.
There are also stacktraces in the output logs, this is due to issue 512
I try writing down the procedure, is this correct? But which is the raw url for "GET kmr notification"? And is this the javascript equivalent for SPR authentication?
">>>" = sent
"<<<" = received
>>>
/commerce/v1/accounts/AAAAAAAAAAAAAA/kamereon/kca/car-adapter/v1/cars/VVVVVVVVVVVVVV/actions/srp-sets?country=COUNTRY
{
"data":
{
"type":"SrpSets",
"attributes":
{
"a" : A.hex().upper(), // A = second result from usr.start_authentication() or from SRP.generate_a() in [this repo](https://github.com/mitchellrj/kamereon-python/blob/146904802301aa0b0008e2bdb3a88ed10ff50acf/kamereon/kamereon.py)
"i" : UserID // = personId
}
}
}
<<< Notification ID
>>> GET kmr notification endpoint (?)
<<< Salt and LoginB (used to calculate the final SRP key "M")
>>> Send request, with "M" in body, inside the "srp" field
<<< "id" of the notification to check
>>> Request the notification with that new id and see the response if it fails or not
A couple of SRP-related functions from here:
def initiate_srp(self):
(salt, verifier) = SRP.enroll(self.user_id, self.vin)
resp = self.session.oauth.post(
'{}v1/cars/{}/actions/srp-initiates'.format(self.session.settings['car_adapter_base_url'], self.vin),
data=json.dumps({
"data": {
"type": "SrpInitiates",
"attributes": {
"s": salt,
"i": self.user_id,
"v": verifier
}
}
}),
headers={'Content-Type': 'application/vnd.api+json'}
)
body = resp.json()
if 'errors' in body:
raise ValueError(body['errors'])
return body
def validate_srp(self):
a = SRP.generate_a()
resp = self.session.oauth.post(
'{}v1/cars/{}/actions/srp-sets'.format(self.session.settings['car_adapter_base_url'], self.vin),
data=json.dumps({
"data": {
"type": "SrpSets",
"attributes": {
"i": self.user_id,
"a": a
}
}
}),
headers={'Content-Type': 'application/vnd.api+json'}
)
body = resp.json()
if 'errors' in body:
raise ValueError(body['errors'])
return body
----------------------
def enroll(cls, user_id, vin):
salt, verifier = '0'*20, 'ABCDEFGH'*64 /// <<--- error? This is supposed to be an hex string...
# salt = 20 hex chars, verifier = 512 hex chars
return (salt, verifier)
The URL for notifications is https://api-wired-prod-1-euw1.wrd-aws.com/commerce/v1/persons/<UserID>/notifications/kmr?¬ificationId=<NotificationID>
And from what I remember you can skip the last part after "kmr" and it will give you all your notifications in a single response.
Regarding SRP implementation, there are different ones exist, and several exist for python. And it is known that the SRP protocol spec is not 100% strict for the implementation details, plus there were different versions and flavors on the market. This was never a big industry standard, though Apple used it with its own implementation and some other companies. So in the end, different SRP implementations will not work with each other just because they have minor differences in the way they calculate crypto payloads. I actually stumbled upon a github community that tried to fix this issue and list compatible ones, but they did not went too far and still had some questions on the spec interpretation.
I don't think I can comment on your code, as I already forgot some of the details. But you can refer to my SRP sample - that's best of my previous understanding anyway.
I don't understand if this pull request is currently working and if SRP authentication is requested also for lock-status or just for engine start.
SRP is only required for remote engine start, and this PR provides reproducible steps for SRP authentication... but it doesn't work.
Lock-status is working fine already, but is not supported by all vehicles.
Did you already try with the ID provided in notifications, kmrUserId ?
actionType: "COMMAND_RESPONSE" commandResponse: {status: 'CREATED'} commandType: "REFRESH_BATTERY_STATUS" kmrUserId: "xxxx" notifDate: "2022-04-29T08:45:31.624261" notificationId: "kmrUserId" personId: "xxxx" vin: "xxxx"
I think yes. You can actually run this sample with your own ids/variables. While the final response from the server is an error due to SRP validation, the entire flow works kinda correctly in this sample. Your car probably does not have the Engine Start endpoint, but instead you can try to lock/unlock the car as it also requires the entire SRP routine.
I don't know how to install/use a not-accpeted PR.
You just need this one file, download it at https://github.com/hacf-fr/renault-api/blob/2c003ef0634b8b0f1c69621c400abdb6cd98aecd/spr.py
To run it you also need renault-api installed. I don't remember exactly, but maybe you also need this srp library installed. Then you just run it with the python and it shows the progress in the log output.
Which values did you test as "pin"?
That's my pin code from the Renault app. This pin code is required by the app when starting engine or locking the doors.
@jumpjack, I think that if the Renault app doesn't allow you to start the engine or to lock the doors, then you won't be able to test it with any integration...
Received an "unimplemented" error rather than a "forbidden" error would be already a good result, there are a couple of dozens of restricted endpoints to test!
-
value = "v1/cars/{vin}/actions/data-reset""
-
value = "v1/cars/{vin}/health-status"
-
value = "v1/cars/{vin}/pressure"
-
value = "v1/cars/{vin}/settings/area_restrictions/{id}"
-
value = "v1/cars/{vin}/settings/speed_restrictions/{id}"
-
value = "v1/cars/{vin}/settings/curfew_restrictions/{id}"
-
value = "v1/cars/{vin}/settings/gfc_restrictions"
-
value = "v1/cars/{vin}/settings/area_restrictions"
-
value = "v1/cars/{vin}/settings/speed_restrictions"
-
value = "v1/cars/{vin}/settings/curfew_restrictions"
-
value = "v1/cars/{vin}/trip-history"
-
value = "v1/cars/{vin}/energy-unit-cost"
-
value = "v1/cars/{vin}/actions/srp-initiates"
-
value = "v1/cars/{vin}/actions/srp-sets"
-
value = "v1/cars/{vin}/actions/stolen-vehicle-tracking-block-unblock"
-
value = "v1/cars/{vin}/actions/engine-start"
-
value = "v1/cars/{vin}/lock-status"
-
value = "v1/cars/{vin}/actions/horn-lights"
-
value = "v1/cars/{vin}/actions/lock-unlock"
-
value = "v1/cars/{vin}/actions/open-close"
-
value = "v1/cars/{vin}/actions/stolen-vehicle-tracking"
https://gitlab.com/tobiaswkjeldsen/dartnissanconnect/-/issues/1