I am using Delphi XE6 and LockBox 3.4.3 to run the code actEncryptStringExecute. This code was posted as an answer to the question 'How to use AES-256 encryption in lockbox 3 using delphi'.
The error I get is TSimpleCodec.Begin_EncryptMemory - Wrong mode.
There is another question 'TSimpleCodec.Begin_EncryptMemory - Wrong mode' where the answer is "You don't need to do this if you are setting up the codec with design-time values. It's much easier to do at design-time. Just set the published properties as required".
TCodec properties are :-
AdvancedOptions2 = []
AsymetricKeySizeInBits = 1024
ChainMode = ECB (with block padding)
Cipher = Base64
CryptoLibrary = CryptographicLibrary1
Encoding = (TEncoding)
TCryptographicLibrary properties are :-
CustomCipher = (TCustomStreamCipher)
Name = CryptographicLibrary1
ParentLibrary =
The code is :-
var
base64CipherText : String;
PlainTextStr : String;
ReconstructedPlainTextStr : String;
procedure TForm1.btnEncryptClick(Sender: TObject);
begin
PlainTextStr := edtPlainText.Text;
Codec1.EncryptString(PlainTextStr, base64CipherText, TEncoding.Unicode);
lblEncrypted.Caption := base64CipherText;
Codec1.DecryptString(ReconstructedPlainTextStr, base64CipherText, TEncoding.Unicode);
lblReconstructed.Caption := base64CipherText;
end;
What do I need change at design time to get this most simple example to work?
Related
Please help me to translate the code. I don't know C++ well, but I know Delphi syntax well. I want to translate code from MSDN:
Step 6. Add Support for COM.
static WCHAR g_wszName[] = L"My RLE Encoder";
CFactoryTemplate g_Templates[] =
{
{
g_wszName,
&CLSID_RLEFilter,
CRleFilter::CreateInstance,
NULL,
NULL
}
};
and
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
I realized that the first line is a variable. But when translated, it does not work. Error:
This is a string and you defined it as WCHAR.
Next comes the description of the structure, but I do not know such a form.
The last line is also a variable, but it has a / and two values.
In general, I kind of understood the meaning, but do not understand how to write it.
The code roughly translates to Delphi as follows:
const
g_wszName: PWideChar = 'My RLE Encoder';
var
g_Templates: array[0..0] of CFactoryTemplate;
...
g_Templates[0].m_Name := g_wszName;
g_Templates[0].m_ClsID := #CLSID_RLEFilter;
g_Templates[0].m_lpfnNew := #CRleFilter.CreateInstance;
g_Templates[0].m_lpfnInit := nil;
g_Templates[0].m_pAMovieSetup_Filter := nil;
and
var
g_cTemplates: Integer;
...
//g_cTemplates := SizeOf(g_Templates) div SizeOf(g_Templates[0]);
g_cTemplates := Length(g_Templates);
I'm trying to utilize the OVH API in Delphi using the REST client. For this OVH requires me to generate a signature, but their documentation does not provide much info on this other than:
"$1$" + SHA1_HEX(AS+"+"+CK+"+"+METHOD+"+"+QUERY+"+"+BODY+"+"+TSTAMP)
They do provide thin wrappers for other languages so I thought I could take a look at those and try to replicate it. I found the following for generating the signature in C# and have extracted the function to be used in a test application.
Test app C# code:
textBox1.Text = GenerateSignature("appSecret", "consKey", 123456789, "PUT", "/path/to/api", "TEST DATA");
The C# result is:
$1$8336ecc5d03640b976e0b3ba005234a3046ab695
I attempted the rewrite the function in Delphi and came up with the following function:
function GenerateSignature(const appSecret, consKey: string;
const currentTimeStamp: LongInt; const method, target: string;
const data: string = ''): string;
begin
var
toSign := string.Join('+', [appSecret, consKey, method, target, data,
currentTimeStamp]);
var
binaryHash := THashSHA1.GetHashBytes(toSign);
var
signature := '';
for var byte in binaryHash do
begin
signature := signature + byte.ToHexString.ToLower;
end;
Result := '$1$' + signature;
end;
And to test it:
procedure Main;
const
APP_SECRET = 'appSecret';
CONSUMER_KEY = 'consKey';
method = 'PUT';
target = '/path/to/api';
data = 'TEST DATA';
CURRENT_TIMESTAMP = 123456789;
begin
Writeln(GenerateSignature(APP_SECRET, CONSUMER_KEY, CURRENT_TIMESTAMP,
method, data));
end;
Both test applications in C# and in Delphi use the same data but produce different outputs. My expected output is:
$1$8336ecc5d03640b976e0b3ba005234a3046ab695
But I end up getting the following output from delphi:
$1$d99fd5086853e388056d6fe37a9e2d0723de151b
I do not know C# very well but it seems to get the hashbytes then convert it to hex and stitch it together. How can I modify the Delphi function I wrote so that I can get my expected result?
Thanks to the last parameter being optional you didn't notice (because no compiler error/warning) that you actually missed one parameter when calling/testing your function, resulting in a text of
'appSecret+consKey+PUT+TEST DATA++123456789' to be hashed. Which is indeed
d99fd5086853e388056d6fe37a9e2d0723de151b
Let me reformat your test to make it more obvious:
const
APP_SECRET = 'appSecret';
CONSUMER_KEY = 'consKey';
CURRENT_TIMESTAMP = 123456789;
method = 'PUT';
target = '/path/to/api'; // Where is this used?
data = 'TEST DATA';
begin
GenerateSignature
( APP_SECRET
, CONSUMER_KEY
, CURRENT_TIMESTAMP
, method
// Forgotten parameter
, data // becomes "target"
);
end;
Consider making const data: string = '' mandatory, too, instead of optional.
I am actually using dwscript with delphi and got stuck with the follwing problem:
I have defined two classes as follows
TClassOne = class
private
FName : String;
public
property Name: String read FName write FName;
end;
TClassTwo = class
private
FName : String;
FClassOne : TClassOne;
public
property Name: String read FName write FName;
property ClassOne: TClassOne read FClassOne write FClassOne;
end;
I am exposing both Classes to DWScript via ExposeRTTI:
dwsUnitExternal.ExposeRTTI(TypeInfo(TClassOne), [eoExposeVirtual, eoNoFreeOnCleanup, eoExposePublic]);
dwsUnitExternal.ExposeRTTI(TypeInfo(TClassTwo), [eoExposeVirtual, eoNoFreeOnCleanup, eoExposePublic]);
This basically is working, because when I insert the follwing lines
var myClassTwo : TClassTwo = TClassTwo.Create;
myClassTwo.Name := 'test';
var myClassOne : TClassOne = TClassOne.Create;
myClassOne.Name := 'abc';
myClassTwo.ClassOne := myClassOne;
myClassTwo.ClassOne.Name := 'xyz'; // Comiler error
var myClassOne2 : TClassOne;
myClassOne2 := myClassTwo.ClassOne; // Compiler error
myClassOne2 := (myClassTwo.ClassOne as TClassOne); // Compiler error
to a DWScript, the first 5 lines are properly compiled, but when I try to access the property of ClassOne within ClassTwo (6th line), compiler throws "no member expected". I understand that this is due to limited RTTI capabilities, but I have no idea how to solve this problem.
Does anybody know how to get access to myClassTwo.ClassOne.Name within the script? Same with Methods, btw.
Thanks in advance!
PS: Added 3 more lines to show more attempts - no success...
I want to create light object data-package to pass between client and server applications.
It is a so simple task, that I can control with only 1 byte, so
each bit in a byte will have a different meaning,
Using only the bit
0 = False
1 = True
Itens I need now:
1 - Loaded from database
2 - Persisted
3 - Changed
4 - Marked to Delete
5 -
6 -
7 - Null Value
8 - Read Only
1) How do I use bit operators in Delphi to check each bit value?
2) How do I set the bit Values?
Solution
After all help, Ill use the next Set
TStateType = (
stLoaded = 0, // loaded from persistance
stNative = 2, // value loaded and converted to native type
stPersisted = 3, // saved
stChanged = 4, // object or member changed
stToDelete = 5, // marked to delete
stReadOnly = 6, // read only object, will not allow changes
stNull = 7 // value is null
);
TState = Set of TStateType;
And for stream -> persistance, this will be the record to be used:
TDataPackage = record
Data: TBytes;
TypeInfo: TMetaInfo;
State: Byte;
Instance: TBuffer;
end;
Thank you guys, for all the answers and comments.
I'd really use a set for this. However, I see you really want a byte. Use sets everywhere then typecast to a byte in the end.
This solution will require much less typing, has support for standard delphi operators and really carries no performance penalty as Barry Kelly has pointed out.
procedure Test;
type
TSetValues = (
TSetValue1 = 0,
TSetValue2 = 1,
TSetValue4 = 2,
TSetValue8 = 3,
TSetValue16 = 4,
TSetValue32 = 5,
TSetValue64 = 6,
TSetValue128 = 7
);
TMySet = set of TSetValues;
var
myValue: byte;
mySet: TMySet;
begin
mySet := [TSetValue2, TSetValue16, TSetValue128];
myValue := byte(mySet);
ShowMessage(IntToStr(myValue)); // <-- shows 146
end;
I would use a set for this:
type
TMyDatum = (mdLoaded, mdPersisted, mdChanged, mdMarkedToDelete, ...);
TMyData = set of TMyDatum;
var
Foo: TMyData;
begin
Foo := [mdLoaded, mdChanged];
if (mdPersisted in Foo) then ...
These are implemented as integers, so you can pass them easily. And I find the code much, much more readable than bitwise operators.
This page describes Delphi operators, including bitwise operators.
It sounds like you need to use the and operator. For example:
const
LOADED_FROM_DATABASE = 1;
PERSISTED = 2;
CHANGED = 4;
// etc...
//...
if (bitFlags and LOADED_FROM_DATABASE) <> 0 then
begin
// handle LOADED FROM DATABASE
end;
if (bitFlags and PERSISTED) <> 0 then
begin
// handle PERSISTED
end;
// etc...
In order to set the flags, you can use OR:
bitFlags := LOADED_FROM_DATABASE or PERSISTED or CHANGED;
I have an integer field in a ClientDataSet and I need to compare to some values, something like this:
I can use const
const
mvValue1 = 1;
mvValue2 = 2;
if ClientDataSet_Field.AsInteger = mvValue1 then
or enums
TMyValues = (mvValue1 = 1, mvValue2 = 2);
if ClientDataSet_Field.AsInteger = Integer(mvValue1) then
or class const
TMyValue = class
const
Value1 = 1;
Value2 = 2;
end;
if ClientDataSet_Field.AsInteger = TMyValues.Value1 then
I like the class const approach but it seems that is not the delphi way, So I want to know what do you think
Declaration:
type
TMyValues = class
type TMyEnum = (myValue1, myValue2, myValue3, myValue4);
const MyStrVals: array [TMyEnum] of string =
('One', 'Two', 'Three', 'Four');
const MyIntVals: array [TMyEnum] of integer =
(1, 2, 3, 4);
end;
Usage:
if ClientDataSet_Field.AsInteger = TMyValues.MyIntVals[myValue1] then
A cast would generally be my last choice.
I wouldn't say that class consts are not the Delphi way. It's just they have been introduced to Delphi quite recently, and a lot of books and articles you'll find on the internet were written before their introduction, and thus you won't see them widely used. Many Delphi developers (I'd say the majority) will have started using Delphi before they were made available, and thus they're not the first thing that one thinks about.
One thing to consider is backwards compatibility - class constants are relatively new to Delphi so if your code has to be sharable with previous versions than they are out.
I typically use enumerated types, with the difference from yours is that my first enumeration is usually an 'undefined' item to represent NULL or 0 in an int field.
TmyValues = (myvUndefined, myvDescription1, myvDescription2)
if ClientDataSet_Field.AsInteger = Ord(myvDescription1) then...
To use a little bit of Jim McKeeth's answer - if you need to display to the user a text viewable version, or if you need to convert their selected text into the enumerated type, then an array comes in handy in conjuction with the type:
const MYVALS: array [TmyValues ] of string = ('', 'Description1', 'Description2');
You can then have utility functions to set/get the enumerated type to/from a string:
Function MyValString(const pMyVal:TmyValues):string;
begin
result := MYVALS[Ord(pMyVal)];
end;
Function StringToMyVal(const pMyVal:String):TMyValues;
var i:Integer;
begin
result := myvUndefined;
for i := Low(MYVALS) to High(MYVALS) do
begin
if SameText(pMyVal, MYVALS[i]) then
begin
result := TMyValues(i);
break;
end;
end;
end;
Continuing on... you can have scatter routine to set a combo/list box:
Procedure SetList(const DestList:TStrings);
begin
DestList.Clear;
for i := Low(MYVALS) to High(MYVALS) do
begin
DestList.Insert(MYVALS[i]);
end;
end;
In code: SetList(Combo1.Items) or SetList(ListBox1.Items)..
Then if you are seeing the pattern here... useful utility functions surrounding your enumeration, then you add everything to it's own class and put this class into it's own unit named MyValueEnumeration or whaterver. You end up with all the code surrounding this enumeration in one place and keep adding the utility functions as you need them. If you keep the unit clean - don't mix in other unrelated functionality then it will stay very handy for all projects related to that enumeration.
You'll see more patterns as time goes and you use the same functionality over and over again and you'll build a better mousetrap again.
When using constants I recommend assigning the type when the data type is a numeric float.
Delphi and other languages will not always evaluate values correctly if the types do not match...
TMyValue = class
const
// will not compare correctly to float values.
Value1 = 1; // true constant can be used to supply any data type value
Value2 = 2; // but should only be compared to similar data type
// will not compare correctly to a single or double.
Value3 = 3.3; // default is extended in debugger
// will not compare correctly to a single or extended.
Value1d : double = Value1; // 1.0
Value2d : double = Value2; // 2.0
end;
Compared float values in if () and while () statements should be compared to values of the same data type, so it is best to define a temporary or global variable of the float type used for any comparison statements (=<>).
When compared to the same float data type this format is more reliable for comparison operators in any programming language, not just in Delphi, but in any programming language where the defined float types vary from variable to constant.
Once you assign a type, Delphi will not allow you to use the variable to feed another constant, so true constants are good to feed any related data type, but not for comparison in loops and if statements, unless they are assigned and compared to integer values.
***Note: Casting a value from one float type to another may alter the stored value from what you entered for comparison purposes, so verify with a unit test that loops when doing this.
It is unfortunate that Delphi doesn't allow an enumeration format like...
TController : Integer = (NoController = 0, ncpod = 1, nextwave = 2);
or enforce the type name for access to the enumeration values.
or allow a class constant to be used as a parameter default in a call like...
function getControllerName( Controller : TController = TController.NoController) : string;
However, a more guarded approach that provides both types of access would be to place the enumeration inside a class.
TController = class
//const
//NoController : Integer = 1;
//ncpod : Integer = 2;
//nextwave : Integer = 3;
type
Option = (NoController = 0, ncpod = 1, nextwave = 2);
public
Class function Name( Controller : Option = NoController) : string; static;
end;
implementation
class function TController.Name( Controller : Option = NoController) : string;
begin
Result := 'CNC';
if (Controller = Option.nextwave) then
Result := Result + ' Piranha'
else if (Controller = Option.ncpod) then
Result := Result + ' Shark';
Result := Result + ' Control Panel';
end;
This approach will effectively isolate the values, provide the static approach and allow access to the values using a for () loop.
The access to the values from a floating function would be like this...
using TControllerUnit;
function getName( Controller : TController.Option = TController.Option.NoController) : string;
implementation
function getName( Controller : TController.Option = TController.Option.NoController) : string;
begin
Result := 'CNC';
if (Controller = TController.Option.nextwave) then
Result := Result + ' Piranha'
else if (Controller = TController.Option.ncpod) then
Result := Result + ' Shark';
Result := Result + ' Control Panel';
end;
so many options! :-) i prefer enums and routinely use them as you describe. one of the parts i like is that i can use them with a "for" loop. i do use class constants as well but prefer enums (even private enums) depending on what i'm trying to achieve.
TMyType=class
private const // d2007 & later i think
iMaxItems=1; // d2007 & later i think
private type // d2007 & later i think
TMyValues = (mvValue1 = 1, mvValue2 = 2); // d2007 & later i think
private
public
end;
An option you haven't thought of is to use a lookup table in the database and then you can check against the string in the database.
eg.
Select value, Description from tbl_values inner join tbl_lookup_values where tbl_values.Value = tbl_lookup_values.value
if ClientDataSet_Field.AsString = 'ValueIwant' then