I try to do login script to the milestone system(Python)
I use Diffie Hellman Algorithm(Exactly like in the docs)
First I send request with my PublicKey
<?xml version="1.0" encoding="utf-8"?><Communication
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Command SequenceId="1"><Type>Request</Type><Name>Connect</Name><InputParams><Param Name="PublicKey" Value="fd53J5tNveG3K8bmnLWEGgFbhweR7yxutLBNf0L54gWYvGqMgCtBC8fjFuBRpzmOCNkXnPDDjf5mnUp32t4hw/ochVVvX5a2/pnjritMLSU5XzZyb5t/zIUtTur/bySib7xQlql1EyM2cUGh7xCAFJ3jhlgtL1Qx6meGEAsyKtoA" /><Param Name="PrimeLength" Value="1024" /><Param Name="EncryptionPadding" Value="ISO10126" /><Param Name="ProcessingMessage" Value="No" /></InputParams></Command></Communication>
then I took the ServerPublicKey from the response
I create SharedKey ,and I encrypt (AES , MODE_CBC)the username and password with this key(padding= ISO10126)
This is the
<?xml version="1.0" encoding="utf-8"?><Communication
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"><ConnectionId>18bf52cc-1807-4eb1-beba-cfa4435f65ab</ConnectionId ><Command SequenceId="2"><Type>Request</Type><Name>LogIn</Name><InputParams><Param Name="Username" Value="mGdQDfZig9bYsr6uRKP+VA==" /><Param Name="Password" Value="dUmWeDLC14aABU+46OWWMA==" /></InputParams></Command></Communication>
In the response for this request I received :
<Result>Error</Result><ErrorCode>16</ErrorCode>
why?I see the 16 is Incorrect public key
what’s wrong with my key?
Hi Moshe
Error code 16 (Incorrect public key) is returned on LogIn command if the server cannot decrypt successfully one of the encrypted parameters (either username or password).
There are many things that potentially could went wrong.
We will need a little bit more information in order try to help you.
- Does it fail 100 % with all the private/public keys that you generate ?
- Have you tried with PKS7 padding? It was implemented first and could be more robust.
- You are using AES-256 right ? With 16 bytes IV and 32 bytes Key ?
- Have you tried to Unit-test your encryption library ?
- Can you provide one private/public key pair from you generation, both base64 encoded, in order to run unit-test against them on the server?
Unit testing helped us a lot during implementation.
In general something like this (Using C# like pseudo-code):
var encryption1 = new DHEncryption(encodingPadding, primeLength);
var encryption2 = new DHEncryption(encodingPadding, primeLength);
var publicKey1 = encryption1.GetPublicKey();
var publicKey2 = encryption2.GetPublicKey();
encryption1.GenerateSecretKey(publicKey2);
encryption2.GenerateSecretKey(publicKey1);
var string1 = Guid.NewGuid().ToString();
var encryptedString1 = encryption1.Encrypt(string1);
var decryptedString2 = encryption2.Decrypt(encryptedString1);
Assert.IsTrue(string1 == decryptedString2);
And repeat that test few thousand times.
Usually 10 000 should be enough.
thank you for your answer
I succeeded to login(I found code example in the internet)
def encrypt(self, data):
mykey = pack_bigint(self._shared_key)
aesiv = mykey[0:16]
aeskey = mykey[16:48]
cipher = AES.new(bytes(aeskey), AES.MODE_CBC, bytes(aesiv))
paddeddata = appendPadding(data, 16, 'Random')
return base64.b64encode(cipher.encrypt(paddeddata.encode())).decode()
I have other question about the Challenge and the ChalAnswer
how I calc the ChalAnswer?
I try to do this:
SHA512((challenge + sharedKey).toUpperCase()).toString(CryptoJS.enc.Base64)
but it returned error code 19
In general that should be.
Your ‘sharedKey’ is Hex encoded string right ?
And is full size of it - not only the first 48 bytes, right ?
I still not successful to run command with challenge,and I got 19 error code
for example:
challenge:
1335110C-E27A-46EC-8F80-BF88E726CCED
shared_key_hex:
4100449cf47b9a53e85abbed694018794056a81fcd6d788367dcc11cafa9d335ccc9e029a8aad010377fc27e5f311c3f39c088970c280658a69c359002ee28993fab1c3dae441340fe21332029553c1f7d4fc7a7d9d2501edc387f1f3a5f08b477f6b7d952e746c0f29f952b0c7435ec374d5a7ce24345aa837ac022693a807a
after that I do this command :
(challenge + shared_key_hex).upper()
1335110C-E27A-46EC-8F80-BF88E726CCED4100449CF47B9A53E85ABBED694018794056A81FCD6D788367DCC11CAFA9D335CCC9E029A8AAD010377FC27E5F311C3F39C088970C280658A69C359002EE28993FAB1C3DAE441340FE21332029553C1F7D4FC7A7D9D2501EDC387F1F3A5F08B477F6B7D952E746C0F29F952B0C7435EC374D5A7CE24345AA837AC022693A807A
do SHA512 on this:
31ee17a76c228b82b4ce27a5dd2a18a79c0d3c39ab22694cf78746860ad589739d63668e0c3a9cd1d9930182c151b9390c2ade78c1f418ca278cee541f1e04c0
encode with base64:
wVQJA/a1mirXuvxj72A7L/134tD2L0Kye0sDTfynj472J7o6twTBzjExxGLQWzj1Fvn4RRT2XstQH5fHmwRaQw==
Hi Moshe,
I’ve tested this sequence of operations on the server.
Up to this :
do SHA512 on this:
31ee17a76c228b82b4ce27a5dd2a18a79c0d3c39ab22694cf78746860ad589739d63668e0c3a9cd1d9930182c151b9390c2ade78c1f418ca278cee541f1e04c0
I get the same result.
(If I read the bytes after hashing - 0x31, 0xee, 0x17, etc)
But after that my Base64 encoded string is different:
Me4Xp2wii4K0ziel3SoYp5wNPDmrImlM94dGhgrViXOdY2aODDqc0dmTAYLBUbk5DCreeMH0GMonjO5UHx4EwA==
So probably conversion from the HEX string to base64 encoded string fails on your side.
Because when we look the first 3 bytes:
0x31, 0xee, 0x17
those in binary are
00110001, 11101110, 00010111
Grouping them in parts of 6 bits:
001100, 011110, 111000, 010111,
Looking at the correspondence table:
https://en.wikipedia.org/wiki/Base64
Those are Base64 encoded to:
M, e, 4, X
Anyway, do you need to support CHAP (challenges) at all.
Mobile server supports 3 types of security enhancements, when works on HTTP
- DH Key Exchange in order to encrypt username and password
- Chap support in order to prevent unauthorized fire of commands
- Full command encryption
But when you connect to the Mobile server on HTTPS, you basically do not need all of them - there you have channel encryption supported out-of-the-box.
So if the MoS you are connecting to has properly configured https certificate, you can skip the part with challenges.
Again, thank you for your response
I fixed the issue of the base64,and it still returned error 19(unfortunately https isn’t a option already)
This is the sequence of operations on the server:
challenge:
7E66E645-2945-4597-B97F-60B403A1DA84
shared_key_hex:
db2c18f72b404dc87246c88fd23786dc2d896c681630bdbec70addc5765f89cae736b3204ad6c50575c3360cdc32adeffff2bbf6c16ce094d2e0c0c4d36a0a62c200b777f2fded895da17fd3e8189213632e8661e6a0468b7a13914aede7e7303da3b16fc5475f4e75e33c8f846b5da1ca1476dfd0c14e1945a5e4e880bd77d9
challenge answer:
tUWMszpLyojFgZTBkjVXkHeGh37T7wJIdei998+8W/mnwOv8N2iFg4Z5d+w7EQXt3Y87Q59Q5BNRGuuMDUZeKA==
request:
<?xml version="1.0" encoding="utf-8"?>
<Communication
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ConnectionId>4712a3c8-16e6-43c1-883e-37d7fa339d16</ConnectionId >
<Command SequenceId="5">
<Type>Request</Type>
<Name>GetAllViewsAndCameras</Name>
<InputParams>
<Param Name="Challenge" Value="7E66E645-2945-4597-B97F-60B403A1DA84" />
<Param Name="ChalAnswer" Value="tUWMszpLyojFgZTBkjVXkHeGh37T7wJIdei998+8W/mnwOv8N2iFg4Z5d+w7EQXt3Y87Q59Q5BNRGuuMDUZeKA==" />
</InputParams>
</Command>
</Communication>
response:
<?xml version="1.0" encoding="utf-8"?>
<Communication
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ConnectionId>4712a3c8-16e6-43c1-883e-37d7fa339d16</ConnectionId>
<Command SequenceId="5">
<Type>Response</Type>
<Name>GetAllViewsAndCameras</Name>
<InputParams />
<OutputParams />
<Items />
<Result>Error</Result>
<ErrorCode>19</ErrorCode>
</Command>
</Communication>
maybe it’s a “challenge” issue?
after I do the Login request I get in the response 100 challenges,and I choose one of them to run GetAllViewsAndCameras command
they have a some timeout?they all valid?
Hi Moshe,
With the above example I receive the same ChalAnswer in the server code.
Challenges indeed do have an expiration time, but it it 1 hour by default - it shouldn’t be that.
But error code 19 is “SecurityError” which is returned exactly when challenge check fails.
Unfortunately there is no advanced logging of that part in the Mobile server (in order to not be compromised security in some way.)
I’m not sure what can I advice you further.