View ProjeQtOr On SourceForge.net
ProjeQtOr - Project Management Tool
Support us on Capterra
OIN - Open Invention Network
ProjeQtOr free project management software - API write issue (PUT / POST) - ProjeQtOr
 
 

API write issue (PUT / POST)

More
07 Jul 2021 12:23 #1 by caccia
Hello,

We are trying to implement some actions using the REST API, in a Java application.
This works fine for GET actions, but fails for PUT or POST.

We seem to have a problem with the implementation of the AES-CTR encryption / decryption : the Java library expects an IV (Initialization Vector) parameter in the encryption function, but there doesn't seem to be such a parameter in the PHP-AES version. 

Do you know how we should set this IV parameter ? (tried setting it to NULL without success) 
Code used is attached below.

 

File Attachment:

File Name: Launch-java.txt
File Size:2 KB


Cheers
 
Attachments:

Please Log in or Create an account to join the conversation.

More
03 Dec 2021 18:29 - 03 Dec 2021 18:35 #2 by kobetsu
And this is the problem I think many persons reported on the forum. Projeqtor uses PHP library for AES:CTR create by Chris Veness (www.movable-type.co.uk/scripts/aes.html). This library uses it's own implementation of AES CTR and generate VI (key) base on password passed to function. Problem is this VI (key) is generated in a little complicated way.

I tried to connect C# to Projeqtor API and point was (probably like you and many others) how to encrypt data in C# using AES CTR. To do this you need to know VI key.

Take a look for projeqtor source code - you can find like like this:
$data=AesCtr::decrypt($dataEncoded, $user->apiKey, Parameter::getGlobalParameter('aesKeyLength'));

As you can see data you send to projeqtor via api are decrypted using function AesCtr:decrypt (from library I mentioned above) and as secret user_api_key is used. There is nowere passed VI key which we are looking for. Again this VI key is generated from user_api_key.

What is inside AesCtr:decrypt:
public static function encrypt($plaintext, $password, $nBits)
{
$blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
if (!($nBits == 128 || $nBits == 192 || $nBits == 256)) return ''; // standard allows 128/192/256 bit keys
// note PHP (5) gives us plaintext and password in UTF8 encoding!

// use AES itself to encrypt password to get cipher key (using plain password as source for
// key expansion) - gives us well encrypted key
$nBytes = $nBits / 8; // no bytes in key
$pwBytes = array();
for ($i = 0; $i < $nBytes; $i++) $pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
$key = Aes::cipher($pwBytes, Aes::keyExpansion($pwBytes));
$key = array_merge($key, array_slice($key, 0, $nBytes - 16)); // expand key to 16/24/32 bytes long
....

So as you see generally user_api_key (used as secret) is expanded and itself again ecrypted by AES. A little complicated to implemenet outside projeqtor.

Unless my analysis is wrong, projeqtor should use something standard (standard for whole world not PHP only).
Last edit: 03 Dec 2021 18:35 by kobetsu.

Please Log in or Create an account to join the conversation.

More
10 Feb 2022 16:05 #3 by MagicBuzz
Hello kobetsu,

I'm trying to write an interface with C# and face the same problem.
Did you finally found a workarround or do you have a C# code sample that works?

I'm stuck there, and I would avoid to wrap and PHP call from my C# program...

Please Log in or Create an account to join the conversation.

More
10 Feb 2022 17:25 #4 by kobetsu
We extended API of PQ by method allowing us to encrypt passed text. It was the easiest way for us.

Please Log in or Create an account to join the conversation.

More
10 Feb 2022 18:21 - 10 Feb 2022 18:23 #5 by MagicBuzz
Thank you for your answer.

I wonder if I will get in the same direction.
I would have prefered to stay unchanged PQ code, but the way the Encrypt function works is making me mad!

I'm running this PHP code from my C# program :
<?
error_reporting(E_ERROR | E_PARSE); // AesCtr::encrypt produces warnings

require_once "aes.class.php"; // From ProjeQtOr source
require_once "aesctr.class.php"; // From ProjeQtOr source

$filename = 'json.dat'; // Input message "{"id":"11", "figgoId":"30"}"
$contents = file_get_contents($filename);
$data = AesCtr::encrypt($contents, $_SERVER['argv'][1], 256);
file_put_contents($filename, $data);
?>

It update my file from
{"id":"1","figgoId":"5"}
To some crypted phrase :
cQJXBgVIBWLhCDG90KlyKw7zZ5093Yjunso75kwBSUPATK8=

Then I send it to the API :
var formContent = new FormUrlEncodedContent(new
{
new KeyValuePair<string, string>;("data", crypted)
});
Console.WriteLine($"Donnée brute : {data}");
Console.WriteLine($"Donnée chiffrée : {crypted}");

HttpResponseMessage msg = await client.PostAsync(string.Concat(url, User.PATH), formContent);
Console.WriteLine(await msg.Content.ReadAsStringAsync());

But still always get this :
Donnée brute : {"id":"11", "figgoId":"30"}
Donnée chiffrée : cQJXBgVIBWLhCDG90KlyKw7zZ5093Yjunso75kwBSUPATK8=
{"error":"invalid API query", "message":""'data' is not correctly encoded for method PUT. Request for correct API KEY""}

Thus when I run several times the same input message I get different encrpyted data, so I really wonder how the server would be able to decrypt it back as it changes other time...
Last edit: 10 Feb 2022 18:23 by MagicBuzz.

Please Log in or Create an account to join the conversation.

More
10 Feb 2022 19:19 - 10 Feb 2022 19:20 #6 by kobetsu
1.
I see you declared encryption 256 by line:
$data = AesCtr::encrypt($contents, $_SERVER[1], 256);
Are you sure your PQ is using 256 ? not 128 ?

2.
Use this code as example:


string strURI = "https://xxxx/api/Delivery";
//"{\"id\":\"1090\",\"name\":\"test\"}";
strData = "XgEJZxQhrmHmPqjzqQ9YdgljeYiBAri7Y73i192XSZFLG8w"; //<--- here put your encrypted string
var content = new StringContent(strData, Encoding.UTF8, "application/json");

HttpClient httpClient = new HttpClient();
httpClient .DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.UTF8.GetBytes($"{<<user_name>>}:{<<user_password>>}")));

var result = httpClient.PutAsync(strURI, content).Result;
string resultContent = result.Content.ReadAsStringAsync().Result;
Last edit: 10 Feb 2022 19:20 by kobetsu.

Please Log in or Create an account to join the conversation.

Moderators: babynusprotion
Time to create page: 0.056 seconds

Cookies settings

×

Functional Cookies

Ce site utilise des cookies pour assurer son bon fonctionnement et ne peuvent pas être désactivés de nos systèmes. Nous ne les utilisons pas à des fins publicitaires. Si ces cookies sont bloqués, certaines parties du site ne pourront pas fonctionner.

Session

Please login to see yours activities!

Other cookies

Ce site web utilise un certain nombre de cookies pour gérer, par exemple, les sessions utilisateurs.