curve25519 base point multiplication using Crypto++ - c++

When we multiply the basepoint of curve25519 with a scalar number, an exception is thrown.
Integer gx(group.GetSubgroupGenerator().x);
Integer gy(group.GetSubgroupGenerator().y);
ECP::Point g(gx, gy);
ECP::Point P(group.GetCurve().ScalarMultiply(g, 3));
Exception thrown at 0x005B4412 in CryptoExample.exe: 0xC0000005: Access violation reading location 0x00000000.
How can we take generator, other than basepoint in this curve?

Integer gx(group.GetSubgroupGenerator().x);
Integer gy(group.GetSubgroupGenerator().y);
ECP::Point g(gx, gy);
ECP::Point P(group.GetCurve().ScalarMultiply(g, 3));
group.GetCurve() is likely returning NULL because no curve has been set. But the curve25519 gear is probably not going to function correctly using the standard way of doing things (like shown at Scalar multiplication on secp521r1 using Crypto++). In fact, if you run the following code:
GroupParameters group;
group.Initialize(ASN1::X25519());
Then the code will result in an exception because the domain parameters are missing in eccrypto.h and eccrypto.cpp:
$ ./test.exe
terminate called after throwing an instance of 'CryptoPP::UnknownOID'
what(): BER decode error: unknown object identifier
The curve25519 gear is special in Crypto++. Rather than using the library's underlying Integer class and typical field operations through GroupParameters object, it uses a constant time implementation from Andrew Moon called Donna. The library then wraps Moon's Donna code and provides most expected operation using Crypto++ objects like PK_Signer and PK_Verifier.
However, "... and provides most expected operation" stops precisely at the lower-level objects like DL_GroupParameters_EC, which is the interface you are trying to use.
You might also want to take a look at the functions available in donna.h:
int curve25519_mult (byte publicKey[32], const byte secretKey[32])
Generate a public key. More...
int curve25519_mult (byte sharedKey[32], const byte secretKey[32], const byte othersKey[32])
Generate a shared key. More...
Those are the scalar multiplications you are looking for. The first curve25519_mult uses a basepoint of 9. The second curve25519_mult allows you to specify an arbitrary basepoint.
donna.h should be a private header, but we had to expose it because of the missing curve operations. However, Donna is still missing functions for Add and Double, though they could probably be exported if needed.
And also see x25519 and ed25519 on the Crypto++ wiki; and Scalar multiplication on secp521r1 using Crypto++ on Stack Overflow.
The x25519 and ed25519 wiki pages actually discuss your problem:
The Crypto++ library uses Andrew Moon's constant time ed25519-donna.
The curve25519 gear appears to be like most other comparable public
key objects in the Crypto++ library but it is mostly a facade. The
Crypto++ classes are just wrappers around Moon's code that present
some of the expected interface for callers. A side effect of the
integration is, there is no general Point, Curve, or GroupParameters
so you can't perform arbitrary calculations with curve25519.
The reason curve25519 is special is, we needed to provide the gear, but wanted to avoid a lot of changes required to properly support it. The library supports short Weierstrass curves well, but has nearly no support for Edwards and Twisted Edward curves.
Eventually curve25519 will be properly added to the library.

Related

Purpose of EVP_EncryptFinal_ex function in OpenSSL

I'm trying to implement AES symmetric encryption using the OpenSSL library. In the encryption examples, after calling the EVP_EncryptUpdate function, the EVP_EncryptFinal_ex function is immediately called. What is the purpose of calling the EVP_EncryptFinal_ex function?
This is strangely only explained in the API documentation of EVP_EncryptUpdate():
If padding is enabled (the default) then EVP_EncryptFinal_ex() encrypts the "final" data, that is any data that remains in a partial block. It uses standard block padding (aka PKCS padding) as described in the NOTES section, below. The encrypted final data is written to out which should have sufficient space for one cipher block. The number of bytes written is placed in outl. After this function is called the encryption operation is finished and no further calls to EVP_EncryptUpdate() should be made.
In general, it will perform any final calculations that cannot be performed without knowing that the last part of the message are being encrypted. Most (lower level) cryptographic libraries contain an update / final notion. Note that in case of OpenSSL the authentication tag is not considered part of the ciphertext.
Although it is considered good practice to call EVP_EncryptFinal_ex, the function doesn't really do much for modes that don't require full blocks of plaintext or padding. Most cryptographic libraries - including OpenSSL - try and encrypt the delivered plaintext as soon as possible; you should however not take that for granted.

How do I access the member `top` of a BIGNUM in OpenSSL 1.1.x?

I'm currently trying to port an old C++ project over from OpenSSL 1.0.2 to OpenSSL 1.1.1. It's worth noting that this is not my code, but from an open source project, and I can't tell exactly what this part is supposed to do.
One file uses this piece of code (simplified for this post):
BIGNUM *d; //Assume this is a valid, populated BIGNUM
int x = d->top;
Unfortunately, the BIGNUM structure is now opaque in OpenSSL 1.1.x, meaning its member, top, cannot be directly accessed anymore.
With that said, I have a few questions:
Is there a drop-in replacement I can use to access top?
What does top represent? (IIRC it holds the MSB of the bignum, but I can't find any place to confirm that)
Otherwise, is there a way I can avoid using top at all?
The code in question is available here, line 196 is where the first instance of d->top can be found.
The entire project is located in this repository.
The full example you linked, copies out the bits from a BIGNUM (for the RSA d exponent) into a different structure. It does not only access d->top (which is the number of used chunks), but also d->d (the pointer to the actual chunks) as the source of the memcpy in the next line.
The canonical way to copy out the bits of a BIGNUM is bn2bin.
As for your specific questions:
Generally speaking, no, as its semantics refer to the internal representation. However, you can easily compute the required size from the BIGNUMs number of bits, which you already have access to.
The number of chunks used to store the BIGNUM
By exporting the function into an appropriately sized target buffer using an export function.

C++ data type greater than 64 bits

I'm trying to write an RSA implementation and need to work with numbers that are 100 bits and larger. Are there any C++ data types that can allow for this?
If by "C++ data type" you mean "primitive integral type guaranteed by the standard", then no.
If by "C++ data type" you mean "primitive integral type that actually exists on my platform", then maybe, but you'd have to tell us what your platform is, and you haven't.
If by "C++ data type" you mean "any type usable in C++", then the answer is trivially of course, since any platform will be able to fit std::array<uint32_t, 4>. You'll have to write some code to use that like a regular integral type, though.
The more general solution is to use a big integer, arbitrary precision or multiprecision library. For example Boost.multiprecision, but you can find lots of others now you know the correct search terms.
Note
Maarten Bodewes makes a good point about security that I completely ignored by just answering the C++ part. You didn't say that your RSA implementation has any security requirements at all, but just in case ...
If you do care about it actually being safe to use in some real application, consider that
100 bits is probably much too weak, and
you may have more security concerns than just the correctness of the algorithm (such as side-channel attacks and malicious input attacks).
These are well outside the scope of this (or any other individual) question, but they deserve some thought and research. Using a multiprecision library indended specifically for cryptographic use is the minimal first step to getting this right.
If you've been using GCC and your computer supports 64-bit architecture, you could use __int128_t datatype in C++ to hold 16-bytes of data (i.e. 128-bits integer). As mentioned by #Batsheba, you could rather use the boost multiprecision library (comes along /multiprecision/cpp_int.hpp) in case you're having any trouble in using __int128_t.

RandomNumberGenerator requirement during RSA encryption and decryption?

I'm trying to encrypt a message with a public key and decrypt the cipher with the private key using crypto++ like this in the shell:
openssl rsautl -encrypt -inkey id_rsa.pub.pem -pubin -in message -out message.enc
and
openssl rsautl -decrypt -inkey id_rsa.pem -in message.enc -out message.dec
Encryption/Decryption is done in separate applications. I started with the example from https://www.cryptopp.com/wiki/RSA_Cryptography.
My code:
std::string publicEncrypt(std::string const& plain) {
auto cipher = std::string{};
CryptoPP::RSAES_OAEP_SHA_Encryptor e(getPublicKey());
CryptoPP::StringSource(plain, true,
new CryptoPP::PK_EncryptorFilter(CryptoPP::NullRNG(), e,
new CryptoPP::StringSink(cipher)));
return cipher;
}
std::string privateDecrypt(std::string const& cipher) {
auto decrypted = std::string{};
CryptoPP::RSAES_OAEP_SHA_Decryptor d(getPrivateKey());
CryptoPP::StringSource(cipher, true,
new CryptoPP::PK_DecryptorFilter(CryptoPP::NullRNG(), d,
new CryptoPP::StringSink(decrypted)));
return decrypted;
}
My questions:
Why is a random number generator (RNG) needed for EncryptorFilter/DecryptorFilter?
The RNG has to be the same for encryption/decription, right? So, how to share between processes?
Using the NullRNG() as recommended by https://stackoverflow.com/users/608639/jww in Unable to do RSA Encrption/Decryption using Crypto++ (isValidCoding is false) leads to
std::exception NullRNG: NullRNG should only be passed to functions that don't need to generate random bytes.
I guess I fundamentally miss something. Thanks for hints and advices.
If I use this code in a unit test with a global RNG, everything works fine.
Why is a random number generator (RNG) needed for EncryptorFilter/DecryptorFilter?
The signing and verification classes are abstract interfaces setup in cryptlib.h. Some cryptosystems use them, others do not. A class will specialize and can forgo using a generator. Sometimes a class does not need a generator for one of the operations. NullRNG can be used if not needed.
The reason RSA needs a RNG during public key operations is message padding. Padding is often part of the message formatting function. As #PuzzlePalace pointed out, OAEP padding is randomized and not deterministic.
The reason RSA needs a RNG during private key operations is blinding. For RSA and other RSA-like schemes (like Rabin-Williams), blinding is just a multiplication by a random value to mask the inversion by the priavte key to recover the original value. Later, after signing or decryption, the blinding value is removed and the result of the operation remains.
Related, a reason DSA or ECDSA would not need a RNG during private key operations is RFC 6979, Deterministic Usage of the Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA). Deterministic signatures don't use randomized formatting or randomized k's.
Another reason a RNG is needed for public key and private key operations is validation checks on the key. For example, a key might be checked to ensure a particular constraint holds, like its prime or it has a particular Jacobi symbol.
The RNG has to be the same for encryption/decryption, right? So, how to share between processes?
No, the generators can be different. The only requirements is they produce a random stream for some reasonable definition of what it means to be "random". Without splitting too many hairs, it means the generator produces a uniform distribution.
You can find more reading on Crypto++ generators at RandomNumberGenerator on the wiki.
If I use this code in a unit test with a global RNG, everything works fine.
One quick word of caution... GlobalRNG is part of the Test namespace. It is defined in test.cpp : 115:
NAMESPACE_BEGIN(CryptoPP)
NAMESPACE_BEGIN(Test)
ANONYMOUS_NAMESPACE_BEGIN
OFB_Mode<AES>::Encryption s_globalRNG;
NAMESPACE_END
RandomNumberGenerator & GlobalRNG()
{
return dynamic_cast<RandomNumberGenerator&>(s_globalRNG);
}
NAMESPACE_END // Test
NAMESPACE_END // CryptoPP
GlobalRNG is a deterministic generator and its not part of the library proper. Your code will fail to compile in the field if you depend on it.
Use one of the other generators discussed at RandomNumberGenerator on the wiki. AutoSeededRandomPool is a good choice.
Using the NullRNG() as recommended by https://stackoverflow.com/users/608639/jww in Unable to do RSA
Encrption/Decryption using Crypto++ (isValidCoding is false) leads to
std::exception NullRNG: NullRNG should only be passed to functions that don't need to generate random bytes.
That information is incorrect. I need to fix it. Thanks.
Interestingly (in a morbid sort of way), Crypto++ took CVE-2015-2141 due to blinding in Rabin-Williams. The blinding value needed to be a quadratic residue; otherwise an attacker could prepare special messages to reveal the private key.
The full paper by Evgeny Sidorov is available at Breaking the Rabin-Williams digital signature system implementation in the Crypto++ library. Here's what the new and improved inverse function looks like after fixing Sidorov's attack (from rw.cpp):
ModularArithmetic modn(m_n), modp(m_p), modq(m_q);
Integer r, rInv;
do
{
// Do this in a loop for people using small numbers for testing
r.Randomize(rng, Integer::One(), m_n - Integer::One());
// Fix for CVE-2015-2141. Thanks to Evgeny Sidorov for reporting.
// Squaring to satisfy Jacobi requirements suggested by Jean-Pierre Munch.
r = modn.Square(r);
rInv = modn.MultiplicativeInverse(r);
} while (rInv.IsZero());
If you read Section 6 of Sidorov's paper, he suggests generating a random r, and then checking the Jacobi symbol of r to ensure its a quadratic residue. If it was not a QR, then try a new random r. The triage used the method, but it showed the scheme slowed down considerably because a random r satisfies the condition with probability 1/16.
However, we knew squaring r ensured we satisfied Jacobi on the first try because r2 mod n was always a quadratic residue. The squaring/multiplication only takes log (exp) (not n log (n)), so it turned out to be a significant speedup over trial and error. Before we released the next version of the library, we switched to the squaring method.

AES Limitations and MixColumns

So we all agree keys are a fixed-length of 128bits or 192bits or 256bits. If our context was 50 characters in size (bytes) % 16 = 2 bytes. So we encrypt the context in 3 times, but the remaining two bytes how will they be stored in the State block. Should I pad them, the standard doesn't specify how to handle such conditions.
MixColumns stage is the most complicated aspect in the AES, however I have been unable to understand the mathematical representation. I have an understanding of the matrix multiplication, but I'm surprised of the mathematical results. Multiplying a value by 2, shift left for little endian 1 position and shift right for big endian. If we had the most significant bit was set as 1 (0x80) then we should XOR the shifted result with 0x1B. I thought by multiplying by 3 it would mean to shift the value 2 positions.
I've checked the various sources on Wikipedia, even the tutorial that provides a C implementation. But I'm more interested to complete my own implementation! Thank you for any possible input.
In the mix columns stage the exponents are being multiplied.
take this example
AA*3
10101010*00000011
is
x^7+x^5+x^3+x^1*x^1+x^0
x^1+x^0 is 3 represented in polynomial form
x^7+x^5+x^3+x^1 is AA represented in polynomial form
first take x^1 and dot multiply it by the polynomial for AA.
that results in...
x^8+x^6+x^4+x^2 ... adding one to each exponent
then reduce this to 8 bits by XoRing by 11B
11B is x^8+x^4+x^3+x^1+x^0 in polynomial form.
so...
x^8+x6+x^4+ x^2
x^8+ x^4+x^3+ x^1+x^0
leaves
x^6+x^3+x^2+x^1+x^0 which is AA*2
now take AA and dot multiply by x^0 (basically AA*1)
that gives you
x^7+x^5+x^3+x^1 ... a duplicate of the original value.
then exclusive or AA*2 with AA*1
x^7+ x^5+x^3+ x^1
x^6+ x^3+x^2+x^1+x^0
which leaves
x^7+x^6+x^5+x^2+x^0 or 11100101 or E5
I hope that helps.
here also is a document detailing the specifics of how mix columns works.
mix_columns.pdf
EDIT:Normal matrix multiplication does not apply to this ..so forget about normal matrices.
In response to your questions:
If you want to encrypt a stream of bytes using AES, do not just break it into individual blocks and encrypt them individually. This is not cryptographically secure and a clever attacker can recover a lot of information from your original plaintext. This is called an electronic code book and if you follow the link and see what happens when you use it to encrypt Tux the Linux Penguin you can visually see its insecurities. Instead, consider using a known secure technique like cipher-block chaining (CBC) or counter mode (CTR). These are a bit more complex to implement, but it's well worth the effort so that you can ensure a clever attacker can't break your encryption indirectly.
As for how the MixColumns stage works, I really don't understand much of the operation myself. It's based on a construction that involves fields of polynomials. If I can find a good explanation as to how it works, I'll let you know.
If you want to implement AES to further your understanding, that's perfectly fine and I encourage you to do so (though you are probably better off reading the mathematical intuition as to where the algorithm comes from). However, you should not use your own implementation for any actual cryptographic purposes. Without extreme care, you will render your implementation vulnerable to a side-channel attack that can compromise its security. The most famous example of this involves RSA encryption, in which without careful planning an attacker can actually watch the power draw of the computer as it does the encryption to recover the bits of the key. If you want to use AES to do encryption, consider using a known, tested, open-source implementation of the algorithm.
Hope this helps!
If you want to test the outcome of your own implementation (any internal state during computation) you can check this page :
http://www.keymolen.com/aes.jsp
It displays all internal states for any given plaintext, key and iv, also for the mixcolumns stage.