I'm looking for a way to use RSA (asymmetric encryption) in VB6. I know CAPICOM can do this in VB6, but this stores the public and private keys in a folder associated with Windows, not in the application's folder (not exactly secure, because if you uninstall your program, but forget to remove the keys manually from the Windows folder that has your keys, the keys are left as evidence that you used encryption, and that can be useful info to those who might be your adversary). I know GPG4Win is a program that does RSA encryption, and does store its keys in its own folder, but it is a standalone program, with no possibility to use it as component in other software. I need a DLL or OCX that will work with VB6 and give me access to RSA cryptography functions (like generating key pairs, encryption, decryption, signing, and validating). I think there are some out there, but these all are commercial products, and quite expensive ones at that. I'm looking for a freeware DLL or OCX that will accomplish this. If there is such, please let me know.
If this is for business-purposes (e.g. for signing documents), then I don't see where the topic of:
"evidence that you used encryption" comes in...
You (or the company) had to, to verify things in document-transfers.
So I assume it is for private purposes - and if it is - why do you need a public-key approach
and not a normal strong cypher-algo (e.g. AES-256) with a strong password, to encrypt/decrypt things?
If you want to avoid the Win-Crypto-API for whatever reason, and use a PubKey-approach
which is implemented "by hand", you could use vbRichClient5, which has support for Diffie-Hellman.
But let me ask you again, are you really sure, that you need a Public-Key-approach at all?
If yes, and it is for a protocol - wouldn't be a CRAM-SHA1 (or some other variation of a
challenge-response-approach) entirely sufficient for your needs?
Olaf
Last edited by Schmidt; Mar 13th, 2014 at 06:15 AM.
I would like to be able to write software with copyprotection. I want to be able to write an activation server, and then write some software that will need to be activated. I want to protect the communication between my software-to-be-activated, and the activation server. The user details (Name, Email, Harddrive Serial Number for hardware locking, etc) that is to be encrypted with a public key, and then sent to my activation server, where it will be stored in its encrypted state. If for some reason I need to view a customer's details (like for viewing their name and email address if I need to contact them), I will then use the private key in my activation server to access the stored user details of the customer.
In this system, it isn't imperative that the key used to encrypt the customer info be private, but the key used to decrypt it must remain private, to prevent others from learning the details of other customers (if they did a man-in-the middle attack like packet sniffing and observed the network data between my cutomers' software to be activated and my activation server), which would allow the forging of an activation key for their software.
Currently, my programming has only been hobbyist programming. But if I can figure out this RSA thing, I can then successfully implement activation-server based copyprotection (the strongest kind of copyprotection), and then I can actually start writing software and selling it. And I don't want to use CAPICOM (I have tried the public key encryption offered by it, and it is terrible, requiring another piece of software just to generate the public/private keypair, and that software is a commandline based program, and it only comes with the Windows SDK). I have found dedicated RSA crypto OCX files, but these are all very expensive commercial packages. I am looking for freeware RSA crypto OCX file. Now you mentioned vbRichClient5 as a DiffieHellman solution. Unfortunately that's not what I need. That locks down the communication between just two individuals. I need RSA, which has a public key accessible to everyone, and a private key only accessible to the person who holds the private key. Now if you can find an RSA variant of vbRichClient5, please let me know.
And this picture shows why I don't use CAPICOM. See this folder here? Even when you use it to generate a key in memory, it stores a copy of the private key in a file automatically. See the linked picture http://i.imgur.com/fp8eYfM.png
RSA is supposed to be useful to protect info. Part of that protection is being able to have deny that any encryption was used. One should be able to have a private key stored only in memory with the option to save to a file (but not forced saved to file as CAPICOM does), or at least saved in a well named file so that finding it and erasing it (with a secure file wiper program) would be an easy task (not giving it an obscure random-number-generator based name as CAPICOM does). That is why I'm looking for a 3rd party RSA encryption OCX control (and not one that is simply a wrapper for CAPICOM functions), preferably one that is freeware (open source isn't important, but not having to pay for it is).
Last edited by Ben321; Mar 18th, 2014 at 10:01 AM.
What have all these "secure disk-wiping to remove traces"-considerations to do with the "Secure Activation-Server" you plan?
Seriously, can you explain that first?
And no, Diffie-Hellman is not bound to only two participants as "Alice and Bob", it is used in practice
for whole groups of participants (IPSec/VPNs) for example.
With some additional considerations in the Authentication-phase (the "Standard-DH-Key-Exchange"
only *one* part of it), the approach is entirely sufficient for a "secure-activation-scenario".
I think I can help you - but please explain first, why you feel the need to:
"remove any traces, that encryption was used"...
I don't want to "harass" you with that, just trying to understand the scenario better.
What have all these "secure disk-wiping to remove traces"-considerations to do with the "Secure Activation-Server" you plan?
Seriously, can you explain that first?
And no, Diffie-Hellman is not bound to only two participants as "Alice and Bob", it is used in practice
for whole groups of participants (IPSec/VPNs) for example.
With some additional considerations in the Authentication-phase (the "Standard-DH-Key-Exchange"
only *one* part of it), the approach is entirely sufficient for a "secure-activation-scenario".
I think I can help you - but please explain first, why you feel the need to:
"remove any traces, that encryption was used"...
I don't want to "harass" you with that, just trying to understand the scenario better.
Olaf
It would also be useful for creating a secure communications setup with others. I could make something where someone could send me messages. They use the public key, and I use my private key. If an adversary ever decided to take a look at my computer, and I caught wind of it, I could simply shut down the computer before my adversary arrived and the private key would be erased from memory if the key only existed in RAM. We are living in some pretty scary times for free speech, with all this NSA illegal spying crap going on that Snowden revealed, and I think a secure communications solution is a good idea, in case the crap-hits-the-fan so to speak. Having a good software activation solution is a related situation but doesn't require quite the same form of security as "sending secret messages" does. Since both topics involve good encryption (the latter also requiring plausible denyability so you can deny you ever were using encrypted communications, if things start going down), I figured I'd mention both scenarios in here. And even GPG4Win has the problem of storing the private key to a harddrive. The ideal situation would be to have it store the private key only in memory, but GPG4Win can't do this. So I decided to write my own RSA software from scratch, and make sure that the private key was only stored in memory (so it would be destoryed whenever the program was shut down or if I pull out the computer's power cord), but quickly realized I was in over my head, working with 4096 bit random prime numbers. That's beyond the scope of my brain to even begin to try to figure out how to write the programming code to pull that off. Then I looked for an OCX or DLL solution, that would implement all the needed Big-Prime-Number generating functions and Big-Integer math functions that would be needed, so that the hardest part of writing RSA would already have been done by the programmer of the OCX or DLL file. Unfortunately all such DLLs or OCXs are commercial packages that cost well over $100. So now I'm just hoping someone here on VBForums may have managed to find an obscure DLL or OCX file somewhere on the net that does what I need it to.
An encrypted and secure (socket-based) communication-mechanism which works out of the Box in high performance,
comfortable to program in a DCOM-like fashion, is already available "for free" with vbRichClient5.dll.
To enable that with this Dll (using its VB6-implemented Diffie-Hellman-Key-Exchange-mechanism in conjunction with a self-generated Public/Private Key-Pair), you would need:
- to create these two Key-Files (a Private and a Public one) per cRPCConnection.CreateNewKeyPair
- the two Files will be created in the Directory where vbRichClient5.dll is located
- these two are meant for the Server and should be placed and remain in the ServerBin-Directory only
- since such a Server is usually placed in a secure location, somebody who plans a MITM-attack would have difficulties to reach the Private-File
-----------------------------------------------
- for the Clients to be able to communicate, they'd have to be provided with the Public-File of the Pair.
- so the Client needs only the Public-File in his vbRichClient5.dll Path - and the server (as said) needs both.
- Clients *without* the Public-Key-File will never be able to establish a communication-channel with the Server
- Clients which have this File, and are able to connect, are guaranteed to talk to only *this* server directly
- for a potential Man-In-The-Middle-attack, the attacker would need both, the Public- *and* the Private-File
- If you manage, to transfer even the Public-Key-Files on a secure channel to your Clients, then you will add additional security.
I will leave it at that - but there exist comprehensive and well-commented Demos, how to use the RC5-RPC-Classes
(two different VB-Example-Projects for a "full-featured" as well as a very simple RPC-Server ...
and a whole bunch of different Example-Clients, which demonstrate the clientside programming with the cRPCConnection-Class).
You will need to tell me, if you trust me enough, to make use of the RC5-libs in such a scenario.
If you trust me not, then the best advise I can give is, to learn C/C++ and compile approriate Sources
from well-known open security-related Projects of the OS-community yourself - or use precompiled binaries
from trusted download-sites for those OS-libs. Then also make *very* sure, that you'll not make any
mistakes whilst implementing your own "higher-level" security around those secure base-primitives.
There's a whole lot which can go wrong, when you're not experienced enough - and Murphy shows up
occasionally as well... seems to love this stuff...
Let me know, if you want to make an attempt with that - then I could provide you with links - and
perhaps additional explanations, should you struggle with the Demos.
Maybe JPBro can chime in here too, if you want to go that route, since he's using the RPC-stuff already
for years in his own projects - so that's not something "knocked together the last week" - it's working
in concrete scenarios for years (about a decade) now.
I understand your concerns about possible NSA-access in certain "official-security-stacks" - but cannot
really follow along with your "plausible deniability" scenario. That's hard to accomplish in either case,
because when somebody comes knocking on your door to "check things in this regard", then you're
"sufficiently suspect, no matter what" (up to "placing evidence on your machine, which never was there").
Though the day we have to explain ourselves about what private means we used, to talk freely
and "undisturbed by eavesdroppers" with our neighbours and friends, is a day where we'd have
"much larger problems all-over". Regimes which resort to this kind of thing, will fall sooner
or later.
An encrypted and secure (socket-based) communication-mechanism which works out of the Box in high performance,
comfortable to program in a DCOM-like fashion, is already available "for free" with vbRichClient5.dll.
To enable that with this Dll (using its VB6-implemented Diffie-Hellman-Key-Exchange-mechanism in conjunction with a self-generated Public/Private Key-Pair), you would need:
- to create these two Key-Files (a Private and a Public one) per cRPCConnection.CreateNewKeyPair
- the two Files will be created in the Directory where vbRichClient5.dll is located
- these two are meant for the Server and should be placed and remain in the ServerBin-Directory only
- since such a Server is usually placed in a secure location, somebody who plans a MITM-attack would have difficulties to reach the Private-File
-----------------------------------------------
- for the Clients to be able to communicate, they'd have to be provided with the Public-File of the Pair.
- so the Client needs only the Public-File in his vbRichClient5.dll Path - and the server (as said) needs both.
- Clients *without* the Public-Key-File will never be able to establish a communication-channel with the Server
- Clients which have this File, and are able to connect, are guaranteed to talk to only *this* server directly
- for a potential Man-In-The-Middle-attack, the attacker would need both, the Public- *and* the Private-File
- If you manage, to transfer even the Public-Key-Files on a secure channel to your Clients, then you will add additional security.
I will leave it at that - but there exist comprehensive and well-commented Demos, how to use the RC5-RPC-Classes
(two different VB-Example-Projects for a "full-featured" as well as a very simple RPC-Server ...
and a whole bunch of different Example-Clients, which demonstrate the clientside programming with the cRPCConnection-Class).
You will need to tell me, if you trust me enough, to make use of the RC5-libs in such a scenario.
If you trust me not, then the best advise I can give is, to learn C/C++ and compile approriate Sources
from well-known open security-related Projects of the OS-community yourself - or use precompiled binaries
from trusted download-sites for those OS-libs. Then also make *very* sure, that you'll not make any
mistakes whilst implementing your own "higher-level" security around those secure base-primitives.
There's a whole lot which can go wrong, when you're not experienced enough - and Murphy shows up
occasionally as well... seems to love this stuff...
Let me know, if you want to make an attempt with that - then I could provide you with links - and
perhaps additional explanations, should you struggle with the Demos.
Maybe JPBro can chime in here too, if you want to go that route, since he's using the RPC-stuff already
for years in his own projects - so that's not something "knocked together the last week" - it's working
in concrete scenarios for years (about a decade) now.
I understand your concerns about possible NSA-access in certain "official-security-stacks" - but cannot
really follow along with your "plausible deniability" scenario. That's hard to accomplish in either case,
because when somebody comes knocking on your door to "check things in this regard", then you're
"sufficiently suspect, no matter what" (up to "placing evidence on your machine, which never was there").
Though the day we have to explain ourselves about what private means we used, to talk freely
and "undisturbed by eavesdroppers" with our neighbours and friends, is a day where we'd have
"much larger problems all-over". Regimes which resort to this kind of thing, will fall sooner
or later.
Olaf
What if I want to protect my clients comms, and someone gains physical access to my machine? I would like to be able to have a way of quickly finding and removing the private key, the moment someone suspicious comes knocking at the door. Think of me as like the "preppers" you've seen on that TV show, only for me I want to prepare my computer for when the-crap-hits-the-fan. Think of me as a "cyber-prepper". That's not my only hobby, but it's one of them. I am trying to come up with an implementation of RSA that isn't based on any big-company-produced software libraries (MS CAPICOM is out of the question, for when it comes to the strongest security, because I've got a hunch that MS put some kind of backdoor into it, under NSA demands). The only RSA implementation I trust will be that which I make myself, or that which has been made by other hobbyist programmers. Now me making it myself is out of the question, as VB6 doesn't come with anything for working with huge integers like those 1024bits+ long. And writing your own multiplication and even writing basic arithmatic (add, subtract, multiply, divide) for these huge numbers is a big task in and of itself. Writing a brute force random prime number generator (randomly picking a number and then checking every possible number below a number to make sure it it isn't a factor of that number, and then picking a new random number and repeating until you find a random number that is prime) is easy for small integers like 1 or 2 bytes in sized. For 4 byte ints, it is a long time waiting for just one round of checking for factors, and can easilly take an hour to randomly pick a prime number. 1024bit+ numbers would take longer than the age of the universe, many times over, just to brute force check all possible factors below a number to be sure it is prime. And since I don't understand the math of how to create an OPTIMISED random number prime checker, then that is out of the question for me writing it (even creating a brute force one for huge ints, would require at least the basic arithmatic functions for huge ints, and I've barely managed to get addition and subtraction working for huge ints (in terms of writing code "from scratch"), and multiplication of huge ints has stumped me entirely. Needless to say, I'll need to get a 3rd party RSA module for this. Unfortunately none of them are free, except the one that uses DiffieHellmen, but DH is not RSA.
Well, seems you are a bit fixed on RSA - although I've already explained, that it is possible to use the principle immanent in Diffie Hellman, to achieve similar things as RSA in Public-Key-based Authentication and MITM-protection.
The vbRichClient5.dll is my own work - and all this "math-stuff" you were talking about is implemented directly in VB6 - didn't use any CAPI-methods for the DH-implementation, because at the time I wrote this, the MS-API-support was weak and incomplete in comparison (still had these 64- or 128Bit export-restrictions with regards to maximum strength etc.).
On todays CPUs the implementation in the RC5 is fast enough (if you can wait a second or two) to handle 1024Bit Primes -
and also to generate random-numbers which are Co-Prime to the DH-modulo-Primenumber.
The VB-Code is using the same very small and still comprehensible numbers as the example
in the Wikipedia-Link.
We need a new VB-StdExe-Project with a Form and two Classes - also needed is a checked in Reference to vbRichClient5:
Into a Class cAlice:
Code:
Option Explicit
Private Const p = 23, g = 5 'those can be choosen as fixed values, and even be published
Public PK_A
Public PK_of_Bob '<- the other participants PK, after the Exchange took place
Private a 'Alices Private-Key is defined as a private member of this Class, never seen outside
Private s 'The finally calculated shared secret is a private member too of course
Private Sub Class_Initialize()
a = 6 'Alice is defining her very own Private Key, nobody else knows (in practise a Random large number is choosen)
End Sub
Public Sub CreatePK_A()
With New_c.Crypt
.DiffieHellmanBase = g
.DiffieHellmanPrime = p
.DiffieHellmanPrivate = a
PK_A = .DiffieHellmanCreatePublicKey
End With
End Sub
Public Sub CalculateSharedSecret()
With New_c.Crypt
.DiffieHellmanBase = g
.DiffieHellmanPrime = p
.DiffieHellmanPrivate = a
.DiffieHellmanPublic = PK_of_Bob
s = .DiffieHellmanCreateSharedSecret
End With
Debug.Print "Shared secret s, printed from inside the cAlice-Class: "; s
End Sub
Into a Class cBob:
Code:
Option Explicit
Private Const p = 23, g = 5 'those can be choosen as fixed values, and even be published
Public PK_B
Public PK_of_Alice '<- the other participants PK, after the Exchange took place
Private b 'Bobs Private-Key is defined as a private member of this Class, never seen outside
Private s 'The finally calculated shared secret is a private member too of course
Private Sub Class_Initialize()
b = 15 'Bob is defining his very own Private Key, nobody else knows (in practise a Random large number is choosen)
End Sub
Public Sub CreatePK_B()
With New_c.Crypt
.DiffieHellmanBase = g
.DiffieHellmanPrime = p
.DiffieHellmanPrivate = b
PK_B = .DiffieHellmanCreatePublicKey
End With
End Sub
Public Sub CalculateSharedSecret()
With New_c.Crypt
.DiffieHellmanBase = g
.DiffieHellmanPrime = p
.DiffieHellmanPrivate = b
.DiffieHellmanPublic = PK_of_Alice
s = .DiffieHellmanCreateSharedSecret
End With
Debug.Print "Shared secret s, printed from inside the cBob-Class: "; s
End Sub
And finally this into a Test-Form:
Code:
Option Explicit
Private Sub Form_Load()
Dim Alice As New cAlice, Bob As New cBob
'this code reproduces the example, as given on Wikipedia
'link: http://en.wikipedia.org/wiki/Diffie-Hellman_key_exchange
Alice.CreatePK_A
Debug.Print "PK_A which Alice can publish: "; Alice.PK_A
Bob.CreatePK_B
Debug.Print "PK_B which Bob can publish: "; Bob.PK_B
'the Public Keys can be openly transferred (exchanged) over whatever channel
'so, in the following sequence Alice just uses Bobs PK and vice versa
Alice.PK_of_Bob = Bob.PK_B
Bob.PK_of_Alice = Alice.PK_A
'now the internal Shared-Secrets can be calculated
Alice.CalculateSharedSecret
Bob.CalculateSharedSecret
End Sub
So you are the guy with the website http://vbrichclient.com/ then ? That's your project? If so, where can I get complete documentation on all the functions, subs, events, etc that it includes? The documentation has just a few things mentioned on that site. Yet there are so many powerful abilities it has (I just tried it out, and it's HUGE, it's got like TONS of useful stuff in it). Unfortunately I don't know how to use much of it, due to a significant lack of documentation. For example, the FastLZCompress function. What are the parameters it has (window size or dictionary size that it uses)? It's got fixed parameters (not editable), but I don't know how this compares to other implementations of LZ compression. Also what variety of LZ is it using? LZ77, LZSS, LZW? I see you have a separate LZMA compression, but I'm confused as to what variation of LZ the FastLZ is. Some help here would be nice. Also I notice that the ZLIB decompression does not ask for "original size". Normally ZLIB requires an input of original size to decompress the data. How does your implementation of ZLIB determine original size when decompressing it? Also I notice while ZLIB doesn't allow different compression levels to be set in your implementation. If I remember correctly, ZLIB normally allows different levels of compression to be set. I've got lots of questions, but can't find much documentation on your DLL. I hope you can answer my questions.
Don't P and G both have to be prime numbers, not just any random number? Furthermore, don't they have to be huge random primes, like the keys? Likewise, don't the keys have to be prime? For example you pick 15 as a private key. But 15 is not prime. Nor is it big. Aren't the keys supposed to be huge primes like at least 1024bits?
Also what is the purpose of the property DiffieHellmanSharedSecret if the method DiffieHellmanCreateSharedSecret already exists to output a shared secret?
If so, where can I get complete documentation on all the functions, subs, events, etc that it includes?
There's a *.chm-File, Dr. Unicode has contributed to the project - but it lists basically the same things
the VB-ObjectExplorer shows too (all the Classes and their Methods+Parameters) - though in a
more "cross-linked manner" perhaps. http://vbRichClient.com/Downloads/RC5Docs.zip
But a whole lot of Classes are covered with quite large and commented Code-Demos
in appropriate Tutorial-Zips.
Originally Posted by Ben321
The documentation has just a few things mentioned on that site. Yet there are so many powerful abilities it has (I just tried it out, and it's HUGE, it's got like TONS of useful stuff in it). Unfortunately I don't know how to use much of it, due to a significant lack of documentation.
Nah, you know how to use it, you just don't know that yet.
Originally Posted by Ben321
For example, the FastLZCompress function. What are the parameters it has
Hmm, the VB-Objectexplorer says:
Sub FastLZCompress(BSrc() As Byte, BDst() As Byte)
..... Member of vbRichClient5.cCrypt
I'm quite sure you agree, that this already is self-explaining enough, to dare an experiment with two ByteArrays (a Source and a Destination)?
Code:
With New vbRichClient5.cCrypt
Dim Src As String, BSrc() As Byte, BDst() As Byte, Dst As String
Src = "The quick brown fox jumps over the lazy dog, ignoring foo, bar, baz and lorem ipsum."
Src = Src & Src & Src 'ensure some redundancy to e.g. simulate XML-content
BSrc = Src 'assign to a Src-ByteArray
.FastLZCompress BSrc, BDst
Debug.Print "Len-Source:"; UBound(BSrc) + 1, "Len-Compr:"; UBound(BDst) + 1
BSrc = BDst 'copy over the Compressed bytes as the new ByteSource, just to keep the names straight for Decompression
.FastLZDecompress BSrc, BDst
Debug.Print "Len-Source:"; UBound(BSrc) + 1, "Len-DeCompr:"; UBound(BDst) + 1
Dst = BDst 'back-conversion into String-Space
Debug.Print IIf(Src = Dst, "Src-String matches Dst-String", "shouldn't happen")
End With
Originally Posted by Ben321
...(window size or dictionary size that it uses)?
It's got fixed parameters (not editable), but I don't know how this compares to other implementations of LZ compression.
Also what variety of LZ is it using? LZ77, LZSS, LZW?
I see you have a separate LZMA compression, but I'm confused as to what variation of LZ the FastLZ is.
Some help here would be nice.
Sure. What about googling, e.g. for the term 'FastLZ' and clicking the first link?
Originally Posted by Ben321
Also I notice that the ZLIB decompression does not ask for "original size".
Normally ZLIB requires an input of original size to decompress the data.
How does your implementation of ZLIB determine original size when decompressing it?
It apparently works with just the two Byte-array-parameters - BSrc and BDst -
what would be your guess on how I implemented that - or differently asked:
how would you implement it, to provide the users of your lib with such a "VB-typical-convenience"?
Right, you would have written a small header with the len-info, preceding
the compressed ByteStream.
I brought that example, to encourage you to use (and trust) your own logic - it will in most
cases not differ from the one I've applied in the implementation-phase of a method.
Originally Posted by Ben321
Also I notice while ZLIB doesn't allow different compression levels to be set in your implementation.
If I remember correctly, ZLIB normally allows different levels of compression to be set.
Yep, 1 to 9 IIRC - I've left it hard-wired to 6 I think - as a good compromise for this
mid-level compression of the ZLib, which is the best "over-all-performer" when we weigh
both - "achievable compression-rate" and "reasonable speed", so I've hardwired it to
a "reasonable middle-position", since there are the other two compressors to choose
from - if you want more speed, choose FastLZ instead of ZLib with compression-strength
at level 1 - in this case FastLZ will be better - same thing in the other direction:
ZLib at level 9 will not reach the compression-rate of LZMA, but gets slower in this case too.
FastLZ achieves 200-400MB/sec throughput in both directions - but its compressed-output
is about 20-30% larger than ZLib at level 6 (which compresses with 20-30MB/sec and
decompresses with ~30-50MB/sec then).
The strongest compressor of the trio is LZMA (the algo used in 7zip) - then at the cost of
somewhat longer compression-times - but this is more in compression-direction - its decompression
speed is not that much off from ZLib.
Originally Posted by Ben321
I've got lots of questions, but can't find much documentation on your DLL. I hope you can answer my questions.
Maybe in different threads, when you try to solve concrete problems with some RC5-Classes,
which might be interesting also for others... we're already a bit off-topic with the compression-stuff
here in this Public-Key-Encryption-Thread.
Olaf
Last edited by Schmidt; Mar 20th, 2014 at 09:18 PM.
Don't P and G both have to be prime numbers, not just any random number?
In the example I've posted p is prime (23) - and the generator g is also prime (5) - but we discussed the topic of what
values to choose for p and g already in the other thread here on vbForums (link is in my previous post).
Originally Posted by Ben321
Furthermore, don't they have to be huge random primes, like the keys?
You don't have read the "official documentation" (e.g. on Wikipedia) ... p needs to be a large prime, g doesn't need to be large at all.
A value of 2 for the generator g is already sufficient and choosen in standard IPSec-implementations (e.g. in VPN-routing-hardware etc.).
The small values you see in the example I've posted, do match exactly with the values in the wikipedia-article,
so that you will see the same results - and can do your own calculations "by hand" as well, to follow the math which is explained on wikipedia.
The example-values are "formally correct" - but choosen extra-small-and-simple for easier reproduction.
Originally Posted by Ben321
Likewise, don't the keys have to be prime? For example you pick 15 as a private key. But 15 is not prime. Nor is it big. Aren't the keys supposed to be huge primes like at least 1024bits?
No, not at all - e.g. when you switch (in cAlice and cBob both) to the following for p and g:
Code:
Private Const p = "197", g = "2" 'those can be choosen as fixed values, and even be published
With p = 197 being prime and with the "officially approved" generator g = 2, the example will output now:
PK_A which Alice can publish: 64
PK_B which Bob can publish: 66
Shared secret s, printed from inside the cAlice-Class: 10
Shared secret s, printed from inside the cBob-Class: 10
Neither the Private Keys a=6 for Alice and b=15 for Bob need to be prime -
nor is the output of both public Keys (PK_A and PK_B) prime.
and neither is the shared secret s, which comes out with 10 in this case.
As for large Primes - sure - I can e.g. post one of the "official Primes" of the
IPSec-algos in 768Bit or 1024Bit length - then you can generate Private
keys from it in a matching length per .CreateRandomNumber(p) - then
also the appropriate PK_A and PK_B will come out in this secure range,
as well as the shared Secret.
Also what is the purpose of the property DiffieHellmanSharedSecret if the method DiffieHellmanCreateSharedSecret already exists to output a shared secret?
To spare yourself the declaration of a variable - it's sometimes nice, to have a class-instance to
pass around as a single parameter, when it already contains everything that's needed in a
given scenario.
Yep, nice and perhaps a better matching example for the OPs goals than the Link I've already posted to a PSC-project, which also makes use of CAPICOM.
Though Ben321 seems not really happy with using the "official OS-stack" for his purposes.
<shrug>
Olaf
That's because the private key is stored in an appdata folder by the system, instead of the program's own folder, and entries are created in the registry, which leaves a lot of stuff behind, which could lead to someone with sufficient investigative skills determining who used encryption and when. If you are using encryption stuff, it is supposed to not be allowed to be traced to you. Windows's own techniques leaves too many traces behind.
If I had an ideal OCX or DLL file for RSA encryption, it would store all the needed keys as files in the program's own folder, and write absolutely nothing to the registry, and not rely on Microsoft's certificate system.
The private key would be used by my program to decrypt things, and the public key could be posted anywhere on the internet so people could send me things without a MITM attack being used to determine what was sent to me, because the data would be encrypted by RSA. And if I suspected somebody might get a hold of my physical computer, I could simply use file-wiping software to remove the key files in the program's own folder, and all evidence of my use of encryption would be gone.
As it is using Capicom which saves a bunch of crap everywhere, including in the registry, by the time I figured out where everything was and tried to get rid of it, someone could have broken in and gained physical access to my computer, and found everything they wanted to.
I have nothing to hide, but I plan on writing software that I plan to distribute on the net, so that others who do have significant security needs will be able to fulfill those needs. And I would NEVER write software and distribute it to those with high security needs, if the software depended on that stupid CAPICOM stuff from Microsoft, which is absolutely NOT secure (and truly secure alternatives are very expensive, which is why I plan to write a completely free program, using your VB RichClient as the core of my program, and distribute it on the net for those with high security needs). I would trust an open source package from you Schmidt MUCH MORE than anything MS created. Your skills at writing Diffie Hellman from scratch, should be easily transferred over to you writing RSA from scratch.
If you are looking into rolling your own using Microsoft advapi32.dll and Crypt32.dll take a look at this source code as a starter:
It is Unicode aware so the demos use UniSuitePlus Unicode controls.
Download at http://www.cyberactivex.com/download/UniSuitePlus.exe
Note that this Exe is an installer built with InstallMate by www.Tama.com
See demo in Program Files \CyberActivex\UniSuitePlus\CryptoSDKvb6
Last edited by DrUnicode; Aug 14th, 2014 at 06:00 PM.
If you are looking into rolling your own using Microsoft advapi32.dll and Crypt32.dll take a look at this source code as a starter:
It is Unicode aware so the demos use UniSuitePlus Unicode controls.
Download at http://www.cyberactivex.com/download/UniSuitePlus.exe
Note that this Exe is an installer built with InstallMate by www.Tama.com
See demo in Program Files \CyberActivex\UniSuitePlus\CryptoSDKvb6
I may be mistaken, but I believe that this is just an alternate way to use CAPICOM, which gets me back to the same problem I was having before, with it storing info about various keys in appdata folders and registry entries.
Actually CAPICOM is a simplified COM wrapper around the crypto API, not the other way around.
I think the notable thing is that nothing meeting your needs already exists. You can buy a DLL or you can find low-level code to do this in C, but there doesn't seem to be anything for free that both bypasses Microsoft's crypto infrastructure and is easy to use from VB6 programs.
This suggests that either sufficient demand never existed in 16 years of VB6 history or that you are being excessively paranoid. Of course in recent years we've learned things that probably ought to make us more paranoid.
Well I dug around in my dusty archives and found something that might work for you. It is fairly low level though and does not implement crypto containers, so you'd have to either roll your own ad-hoc format (as in the demo here) or implement one of the standard ones.
The library was originally meant for use in VBScript code, either in ASP pages, HTML pages (client side), or other containers such as MSHTA or NSBasic on both WinNT and WinCE based systems. It is also old, not really ever completed to the extent promised (or hoped), and seems to have a few rough spots where the run time behavior doesn't quite seem to match up with the documentation.
However the library and related documentation are still available:
While meant as a supplement to or adjunct of newobjectspack1.dll, HashCryptStreams.dll can be used and deployed without the other library.
There isn't a developer install package, so I generally put these into the folder:
C:\Program Files\Common Files\newObjects\ActiveX
Then they can be registered simply by going into an elevated VB6 IDE, opening a new Project, and "adding a reference" using the Browse button to locate the desired DLL. VB6 will register it and in the future it will just show up in the list of registered libraries.
They also don't come with .DEP files, but most people who even know what those are can create their own if desired.
It's a "quick and dirty" one so it does a few things that could be handled better in a "real" application. Note lots of odd fiddling around here and there, mainly because these newObjects libraries are very script-oriented and like Variant variables. When used in a VB6 program you can expect nasty IDE crashes unless you are careful to pass Variants in several places, primarily ByRef parameters to methods.
There are 3 file formats used here, completely ad-hoc:
Keys file - Holds generated keys.
PublicKey file - Holds key info required for a correspondent to encrypt a message.
Message file - Holds encrypted message that the "owner" can decrypt.
There are also 3 small VB6 programs:
KeyGen - To be run once to create the public/private key pair and write them to the two keys files.
Correspondent - To be used to write and encrypt a message.
Owner - To be used to decrypt and read the encrypted message content.
One thing that nags at me is this snippet from CorrespondentUI.frm:
Code:
With AES
For BlockStart = 1 To Len(Msg) Step .BlockSize
'String (even Variant String) blocks don't seem to be reliably
'accepted by Encrypt() despite the documentation, so we create
'a Variant Byte array instead:
BlockBytes = Mid$(Msg, BlockStart, .BlockSize)
Block = BlockBytes
Cipher = .Encrypt(Block, False)
If Not IsEmpty(Cipher) Then Buffer = Buffer & Cipher
Next
Cipher = .Encrypt(Empty, True)
If Not IsEmpty(Cipher) Then Buffer = Buffer & Cipher
.Reset
End With
If the SymmetricCryptObject (AES here) indeed has trouble encrypting pieces larger than its .BlockSize this code should fail. The loop and the Mid$() function are using the .BlockSize value as a character count and not a Byte count, so we actually encrypt 2 * .BlockSize each iteration.
However it works fine, so I may have to experiment some more... if I care enough. I just hate to leave a code sample like this in my pile of working example code with potential bugs and open issues left in it.
It appears that the problem has to do with trying to encrypt a String value with the .codePage property set to anything besides 0 (default, current ANSI), 1251, 1252, or other ANSI codepages preinstalled. In particular the value -1 (supposedly Unicode) fails hard.
Even using an ANSI encoding, I don't see any way to decrypt something encrypted that way.
So ignoring all of that and just stuffing Unicode String data into Byte arrays everything seems to work as documented without too much fuss. If you want to use ANSI just use StrConv(), if you want UTF-8 use a few API calls.
Here is the same demo as above with a little bit of code simplification.
I may be mistaken, but I believe that this is just an alternate way to use CAPICOM, which gets me back to the same problem I was having before, with it storing info about various keys in appdata folders and registry entries.
I can't vouch for CAPICOM but I don't see API CryptExportKey writing keys anywhere.
CryptExportKey generates Public and Private Blob (byte arrays) based on KeyLength and it is then up to the programmer to write these byte arrays to files (or Registry) if desired. This could easily be App.Path.
Well I dug around in my dusty archives and found something that might work for you. It is fairly low level though and does not implement crypto containers, so you'd have to either roll your own ad-hoc format (as in the demo here) or implement one of the standard ones.
The library was originally meant for use in VBScript code, either in ASP pages, HTML pages (client side), or other containers such as MSHTA or NSBasic on both WinNT and WinCE based systems. It is also old, not really ever completed to the extent promised (or hoped), and seems to have a few rough spots where the run time behavior doesn't quite seem to match up with the documentation.
However the library and related documentation are still available:
While meant as a supplement to or adjunct of newobjectspack1.dll, HashCryptStreams.dll can be used and deployed without the other library.
There isn't a developer install package, so I generally put these into the folder:
C:\Program Files\Common Files\newObjects\ActiveX
Then they can be registered simply by going into an elevated VB6 IDE, opening a new Project, and "adding a reference" using the Browse button to locate the desired DLL. VB6 will register it and in the future it will just show up in the list of registered libraries.
They also don't come with .DEP files, but most people who even know what those are can create their own if desired.
A bit of a problem I found with that. When I run CreateRandomKeys, and then check each of the outputs, I see that these things have been correctly generated:
P
Q
Modulus
Secret Exponent (part of the Private Key)
Unfortunately, the Public Exponent (part of the Public Key) is not generated correctly. Here's the code for test program I made just to make sure everything was working.
Code:
Dim a As New RSACrypt
Private Sub Form_Load()
a.CreateRandKeys
With a
Print "P Length = "; CStr(UBound(.P) + 1)
Print "P = "; StrConv(.P, vbUnicode)
Print ""
Print "Q Length = "; CStr(UBound(.Q) + 1)
Print "Q = "; StrConv(.Q, vbUnicode)
Print ""
Print "Modulus Length = "; CStr(UBound(.Modulus) + 1)
Print "Modulus = "; StrConv(.Modulus, vbUnicode)
Print ""
Print "Public Exponent Length = "; CStr(UBound(.PublicExp) + 1)
Print "Public Exponent = "; StrConv(.PublicExp, vbUnicode)
Print ""
Print "Secret Exponent Length = "; CStr(UBound(.SecretExp) + 1)
Print "Secret Exponent = "; StrConv(.SecretExp, vbUnicode)
End With
End Sub
Private Sub Form_Unload(Cancel As Integer)
Set a = Nothing
End Sub
And here's a screencap of the output.
As you can see, the length of the public exponent is only 3 bytes! It should be the same length as the secret exponent, which is 33 bytes (or at least should be a lot longer than 3 byte output that it's giving now). Is this some bug in the DLL file? I also noticed that while P is 16 bytes long, Q is 17 bytes long. Why this discrepancy?
Also, what's the difference in this DLL between the RSACrypt class and the RSACryptFree class?
Maybe my problem is missing dependencies? You suggest that there are some dependencies when you say:
They also don't come with .DEP files, but most people who even know what those are can create their own if desired.
But you never say what they are, so I have no more info to go on. I'm stuck now, at a brick wall in my programming, because I don't know what to do next to fix this glaring bug.
In this case there shouldn't be any dependecies that aren't part of Windows, so the DEP file you'd want would tell packaging software that (along with the other things like dates that go in there).
The RSACrpytFree is for use in free-threading environments, so it doesn't apply to VB6.
I'm not sure what is going on with P, Q, and the public exponent. However I think what is happening is that non-significant zero bytes are truncated by this library when it exposes these values, i.e. it uses a "big number" implementation where values are variable length.
Why would you think P should be the same "length" as Q? Or that D and E should be the same "length" (or any specific length)?
But it does seem to be creating a 3-byte E every time, at least in several trials here. Is it a bug? A weakness in the implementation?
I don't know. I'm no crypto expert and I haven't compared this with other RSA encryption software's output.
Last edited by dilettante; Aug 29th, 2014 at 10:45 AM.
What was wrong with DrUnicode's suggestion above anyway?
I looked through both the old CryptoAPI and the newer CNG API in Windows. It looks like recording things to various keystores on disk is optional in both cases.
3 bytes {1,0,1} in RSAParameters.Exponent is a standard recommended public
exponent = 2^16 + 1 = 65537 = 0x10001. It is recommended because it gives
good performance for operations involving public key (due to low hamming
weight). 3 as public exponent gives better performance, but 3 exponent could
not be used to encrypt the same message to more than two different
participants (i.e. public exponent 3, but different modulus) otherwise
message could be easily recovered. With 0x10001 it could be a threat only if
you send the same message encrypted with more than 65536 different public
keys that uses 0x10001 as public exponent - which is much higher threshold
and isn't usually a practical threat. 3 and 2^16+1 as public exponent have
best performance of encryption and signature verification, least amount of
messages that encrypts to themselves (message convolution), guarantees that
private exponent will be big and not be vulnerable to Weiner attack; +++.
Because it uses the same public exponent, that makes it extremely insecure it says. That means if I want to send the same message to 10 different recipients, each using a different private exponent (and me using a different modulus for each one), then it would be quite insecure. As having multiple contacts receive the same message is a very common situation, particularly with online communications (such as email). So I have decided that the DLL you have suggested is not secure enough. I'm looking for an RSA Encryption/Decryption library that is:
Freeware
Works in VB6
Does not use the Windows Crypto API
Does not use 0x010001 as the public exponent, but instead generates a completely random public exponent, modulus, and private exponent, when the keygen is run.
All four of those conditions must be met, before I consider it to be a viable for any application that I may use it for.
If it is not freeware, I'm can't use it (I don't have enough money to buy an expensive commercial encryption library).
If it is not usable in VB6, I can't use it, as VB6 is the only programming language which I am fluent in sufficiently to make practical software with it.
If it uses the Windows Crypto API, it leaves too much stuff behind, for me to it consider secure, and I won't use it.
If it uses 0x010001 as the public exponent it is not secure enough for my use, and I won't use it.
Your recommended DLL is freeware, it works in VB6, and it doesn't leave a bunch of junk around the harddrive. However, it uses the public exponent whenever it generates a key-pair. The fact that it always uses the same public exponent 0x010001 (which faces the problem of being so short, and also of being the same every time), is deal-breaker for me.
I therefore must repeat my request to you @dilettante and ask that you find a different library for me (or, using your extensive knowledge of encryption algorithms, write one for me). And it must meet all 4 of the above requirement. If it lacks any one of those requirements, I will not use it. Having 3 out of 4 of those requirements is not sufficient. And don't just point me to a commercial crypto library. As I said, one of my requirements is that it be freeware, so if I have to pay for it, I won't use it.
Wow, you seem to expect a lot from a programmer's forum site!
One of the classic bits of wisdom is that rolling your own cryptography isn't very smart. There are just too many ways to do something wrong. I'm sure no crypto expert and would not attempt such a thing myself.
I worry enough about whether I'm using well known and trusted crypto libraries properly!
You didn't seem to read what I wrote: the Windows Cryptography API Next Generation stock provider (bcrypt.dll) that ships in Windows does exactly what I described. That is, as far as I can tell from several tries it uses 3 bytes that are always 01 00 01. I have no reason to think the legacy CryptoAPI does anything different.
As far as I can tell almost nobody ever uses anything different anymore, and in earlier times to speed things the other values used were 03, 05, 11, or 01 01 - all of which are shorter.
Indeed, the relavant portion of that quote above appears to be:
With 0x10001 it could be a threat only if you send the same message encrypted with more than 65536 different public keys that uses 0x10001 as public exponent - which is much higher threshold and isn't usually a practical threat.
I can find no evidence that either of the Windows cryptography APIs results in "junk left all over the hard drive." Stuff only gets written to the hard drive if you ask it to do so, such as by calling the Key Storage Functions which are completely optional. CAPICOM may be another story of course, and when you use a high level wrapper like that you often sacrifice some control.
So I'm pretty much done. Clearly either the legacy CryptoAPI or CNG are perfectly adequate, and if you don't trust those the newObjects' HashCryptStreams library should work just fine.
i am with dilettante here. i have used win crypto api rsa and others in the past and i do not understand why you consider this beeing insecure. i also think that you are pretty lonesome with this point of view.