Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How can we do Rfc2898 in VFP? 2

Status
Not open for further replies.

Rajesh Karunakaran

Programmer
Sep 29, 2016
549
MU
Hi Team!

As a part of an encryption process (type AES using vfpencryption71.fll), I have to do a 'Rfc2898' (available in 'Rfc2898DeriveBytes' class of .Net). Is there any community library which can help me in this?

Thanks in advance,
Rajesh
 
The first thing, which comes to mind is using the wwDotnet Bridge, to be able to use the original .NET class. See
When you want to be able to use assemblies and also even think about Dotnet migration as a future path, the Dotnet bridge is a good way of getting there and starting with it, you'll once need to deep dive into using the bridge, that's not much work but has some hurdles. The bigger issue - though it doesn't seem so - is ensuring a .NET framework version exists. So a related setup strategy like ClickOnce is useful to let your setup detect this and even make it an automatic side installation (it's not the only way, but Craig Boyd has shown how to use ClickOnce here: )

I say this because you can nowadays have upward compatibility issues with .NET usage, ie you might need to ensure an older .NET framework to be present to use a class the way your code does. MS has not dropped the virtue of backward compatibility, but like many other major development platforms (JAVA, PHP and more modern web development stacks) MS also has adopted the virtue of letting things deprecate and become invalid to not need to maintain all code ever implemented and keep all that safe. That demands upgrades of many aspects you'd rather never need to touch again once they're done.

Another option, though no gateway to that .net class itself, is the samples of using the crypto API coming with VFP9 itself: _crypt.vcx in the FFC folder. I don't think just a provider change, so the correct init parameters will make it use this new functionalities of RFC2898, so you'd need to find new API functions to add to the Aapideclarations method and code using the API functions in there.

The major downside of that is, a lot was added to the crypto API since the time VFP9 was released since we don't get any more VFP updates we also don't get FFC class updates that keep up with those changes. You'll not need to extend the library to make use of all new features, you can aim for that single functionality, but its a task to identify which crypto API extension corresponds to that .NET assembly. It's likely not just another cryptographic provider you could use with the unchanged FFC class by simply specifying it as Init() parameter. So it's unknown how much you'll need to dive into MSDN library documentation to get to this specific functionality.

I haven't deep dived into both ways. It would be obviously simpler in and for this moment, to use the Dotnet Bridge and I recommended it previously anyway (see thread184-1734668).

Neither way will be done in minutes. So I'd spend a few hours understanding both ways and their consequences. To be clear, when you pick the Dotnet bridge way, there are two ways to keep your code working:
1. Ensure a library version that works is present.
2. Adapt your code when the assembly changes not downward compatible.

In any case, it also means when you have customers, that only buy one version of your software and don't upgrade often or ever, your software may stop working with n incompatible .net framework change not under your control. That's also not impossible when you use the API without going through .NET, but I'd say an API usage is less likely to break. The point in question still is, whether the RFC related function is available as usual DLL function you can declare in VFP.

You don't have that much of .NET innovation pressure by only using one assembly, but all advanced platforms today have that pressure on top of keeping up with any changes law and users want from you. And even in PHP you still see developers failing to see how PHP mysql functions have deprecated and need to be replaced by mysqli or pdo. No matter if you know that or not: Just notice even with long grace periods (many years a language supports old and new ways of doing things) code often sticks to old ways and that's not even about the usual technical debt developers are responsible for themselves.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Rajesh,

The OpenSSL library has a function to perform that kind of hashing. What Olaf pointed out has huge potential, of course, because bridging to .Net opens your application to a vast plethora of tools and functionalities.

Nevertheless, if you want to keep a narrower focus on the problem, you may use the OpenSSL library.

So, start by locating an appropriate version of libcrypto.dll. The OpenSSL for Windows that I have installed in my system includes a libcrypto-1_1.dll, which is fairly recent and will do for the purpose of demonstration.

Code:
m.OpenSSL_DLL = LOCFILE("libcrypto-1_1.dll")

The required functions in the library that you need to declare identify a digest (in this case, SHA1) and perform the RFC2898 DeriveBytes hash function.

Code:
DECLARE INTEGER EVP_sha1 IN (m.OpenSSL_DLL) AS OpenSSL_SHA1
DECLARE INTEGER PKCS5_PBKDF2_HMAC IN (m.OpenSSL_DLL) AS OpenSSL_Rfc2898DeriveBytes ;
    STRING Password, INTEGER PassLen, STRING Salt, INTEGER SaltLen, INTEGER Iter, INTEGER Digest, INTEGER KeyLen, STRING @ Out

Now, to build the hash you just prepare the parameters and call the function.

Code:
LOCAL Secret AS String
LOCAL Salt AS String
LOCAL Iterations AS Integer
LOCAL Result AS String
LOCAL KeyLen AS Integer

m.Secret = "abracadabra"
m.Salt = "salted" + CHR(0) + "peanuts"
m.Iterations = 2001
m.KeyLen = 32
m.Result = REPLICATE(CHR(0), m.KeyLen)

IF OpenSSL_Rfc2898DeriveBytes(m.Secret, LEN(m.Secret), m.Salt, LEN(m.Salt), m.Iterations, OpenSSL_SHA1(), m.KeyLen, @m.Result) = 1
   ? "Derived key (in hex):", STRCONV(m.Result, 15)
ELSE
   ? "Ops, something went wrong..."
ENDIF
 
I agree with atlopes. That example at hand I also wouldn't go into researching the Windows Crypto API to include that. I'm sure it does. Say what you want about Microsoft, they will keep their Crypto API up to date with all relevant crypto algorithms. But the usage within the Windows Crypto API will be more complex for sure.

That thought only is relevant, if you'd like the simplicity of a DLL DECLARE against the more complex Dotnet bridge usage.

And last not least there's a reason for OpenSSL, that is quite the same reason Craig Boyd once did his FLL: Easier access to cryptographic algorithms, besides all ideas of free open-source software, too.

The one thing MS is capable to do with its crypto API no third party DLLs can do is to keep the crypto API DLLs in a high-security area of the OS, like the kernel is, ie AFAIR MS crypto API DLLs are hardened against the mechanism of DLL hijacking and against replacement of the DLL files themselves. I don't find the references I had about this, so take it with a grain of salt. This "from the top of my hat" knowledge goes back to XP times and may also be outdated, though if I remember correctly I can't think MS gave up on this in the meantime.

Using the Dotnet bridge you would end up using MS crypto code, no matter, whether the assembly is a wrapper or reimplements the algorithms, MS won't use two code bases to do the same things.

Bye, Olaf.

Olaf Doschke Software Engineering
 
You're making a good point, Olaf, the one about the safety of the DLLs.

In the case of VFP, the application file can safely host a certified version of a crypto library, like OpenSSL's, and securely deploy it just in time to be referenced and used. Of course, that wouldn't prevent any attack on the application itself, but at least its target and MO would have to be much more specialized than just a general DLL file hijacking.
 
Dear Olaf,

I have heard of wwDotnetBridge and perhaps a downloaded copy (old one) as well. But, I have not tried using it! Now, will do that.
Thank you so much for such an elaborate reply, as usual!

Dear atlopes,

Could you share the most appropriate url to download that 'libcrypto-1_1.dll' ?
I would need both 32 and 64 (if they are in different files).
When I searched, I got many url but am a bit afraid to go to those unfamiliar sources. Could you help me?
Thanks in advance

Rajesh

 
Dear Olaf,

I will be using DotNetBridge only in a particular module. So, once I load it through 'DO wwDotNetBridge' command, after my purpose is completed, how do I clear it from memory (I mean something similar to "RELEASE LIBRARY vfpCompression71.fll")?
Or, is it like that's not necessary in case of DotNetBridge?
Could you advice?
Thanks
Rajesh

 
Just look at the source code of wwdotnetbridge.prg, the Unload method of the wwDotNetBridge class unloads the CLR runtime. And as the comment says you don't call that, it's an event that runs, when you set the dotnetbridge object to .NULL. The comment also hints on the only case you still may call it, when you want to switch to use another CLR version without reinstantiating the whole class once more.

Any .net class you instantiate also just needs to be set null to be disposed of, unless it's an unmanaged class and needs an explicit dispose call. This means for any single class used via the bridge the rules of disposing of VB.NET/C# apply.

In today's computers, RELEASE LIBRARY or CLEAR DLL or CLEAR CLASS/CLASSLIB are quite obsolete. They restore some RAM, but they also mean you need to fetch an FLL, DLL, VCX (class) again next time of usage.
You have enough memory to keep things you use resident, as even a large application will not load so much code, that it convolutes memory as much.

I'd only dispose unmanaged classes.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Dear Olaf / atlopes,

Both the solutions have their advantages to a great extend.
However, to match exactly with the requirement of the API end (it was for an API in fact), we're now writing a dotnet dll and then we would utilise the functionality by calling them from vfp. This will eliminate confusions and any doubt points, I believe.

Thank you so much for your help
Rajesh
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top