I have an X.509 certificate and need to get the size of its key (in bits) - e.g., 1024 2048 etc. I have looked at X509Certificate2 and also the bouncycastle X509Certificate classes but can't see how to get the key size.
You surely have access to the public key. The key length is public key's size: this.PublicKey.Key.KeySize;
To see an implemented solution, check out this article on MSDN
Related
I have an application that works with smartcards that have RSA certificates on them
For some reason manufacturer does not fill CKA_LABEL on them, so i fidn private key object for RSA like this:
RsaKeyParameters rsaPubKeyParams = (RsaKeyParameters)pubKeyParams;
privKeySearchTemplate.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_KEY_TYPE, CKK.CKK_RSA));
privKeySearchTemplate.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_MODULUS, rsaPubKeyParams.Modulus.ToByteArrayUnsigned()));
privKeySearchTemplate.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_PUBLIC_EXPONENT, rsaPubKeyParams.Exponent.ToByteArrayUnsigned()));
now i have to support smartcards that have ECDSA certificates, no CKA_LABEL also
SO the question is how can i find according private key like with RSA ?
Note: all smart cards have 2 certificates (auth,sign) in random order, so i cant just take first or last object found:
ECPublicKeyParameters ecdsaPubKeyParams = (ECPublicKeyParameters)pubKeyParams;
privKeySearchTemplate.Add(session.Factories.ObjectAttributeFactory.Create(CKA.CKA_KEY_TYPE, CKK.CKK_ECDSA));
-----some more params needed to identify the needed the private key
If it is the same curve, you can't.
A workaround would be to test a signature/verification, then if match, assign CLA_LABEL to optimize for next time.
If you set a unique LABLE or ID for key, you can recover key-pair easily. Then, public key is the one which has CKA.CKA_VERIFY attribute as True and private key is the one which has CKA.CKA_SIGN attribute set to True.
Another tip: for RSA you have its modules and exponent, for elliptic key you have its ec-point CKA.CKA_EC_POINT which is unique for any elliptic-public-key.
I'm trying to encrypt (and decrypt) messages send from one device to another by using NSec.Cryptography, but I find the documentation a bit vague. As I understood I need a Key and PublicKey of device A and B, respectively. I can turn these into a SharedSecret:
var sharedSecret = KeyAgreementAlgorithm.X25519.Agree(encryption.Key, deviceKey);
However, this shared secret doesn't seem useful for encryption as the Encrypt(...) method asks for a Key in its parameters:
var cyphertext = AeadAlgorithm.ChaCha20Poly1305.Encrypt(sharedSecret, nonce, new byte[0], message);
^-- will not work
I have multiple questions:
What is the use of SharedSecret if it can not be used to encrypt?
How is the ChaCha20Poly1305.Encrypt method useful if it uses one key which can't be a shared secret?
How do I encrypt a message using the private key of A and public key of B (like box and secret box in libsodium)?
Note: I wanna use X25519 keys.
Read the documentation for SharedSecret:
Represents the output of a key agreement and the input for key derivation
So you first need to generate one or more keys using a specific KDF and NSec seems to implement HKDF (using SHA-256 or-512, I'd prefer the latter because it is more secure and - on 64 bit machines - possibly even faster. The shared secret itself is not fully random to an adversary, so a KDF is required to create the most cryptographically secure keys from it.
This should answer 1 & 2: SharedSecret is used to derive the actual keys, it isn't a key in itself.
How do I encrypt a message using the private key of A and public key of B (like box and secret box in libsodium)?
As for 3: You need an ephemeral key pair on the sender A and the public key of receiver B. Then you perform the key agreement & key derivation (as above) using the sender's ephemeral private key and send the ephemeral public key with the ciphertext. Don't forget to destroy the ephemeral private key of the sender after the key agreement; you don't need it anymore, and leaking it will compromise the ciphertext.
The receiver can now perform the same agreement using their static private key and the received ephemeral public key, and finally decrypt the message.
In my scenario, I would like to encrypt a very big number (10^27) using a private key and later be able to decrypt it using a public key. The problem I have is that I want to keep the size of the encrypted text as small as possible.
I know that .NET has support for public key encryption (RSACryptoServiceProvider), but the encrypted text gets so huge.
Would it work to instead treat the private key as a public key?
Would Elliptic curve cryptography produce a smaller output?
First of all, if you want to achieve confidentiality you should always encrypt with the public key, not the private key. RSA encryption is not defined for encryption with the private key, and the results may vary (especially the kind of padding that is applied).
For direct RSA encryption, the size of the encrypted message is identical to the modulus. Now the modulus should be at least 2048 bits by now, and your message is only about (27/3)*10=90 bits. So RSA would have a large overhead, independent on the key used. Using ECIES is therefore likely to give significant benefits.
Is there any way to perform private key encryption in C#?
I know about the standard RSACryptoServiceProvider in System.Security.Cryptography, but these classes provide only public key encryption and private key decryption. Also, they provide digital signature functionality, which uses internally private key encryption, but there are not any publicly accessible functions to perform private key encryption and public key decryption.
I've found this article on codeproject, which is a very good start point for performing this kind of encryption, however, I was looking for some ready-to-use code, as the code in the article can hardly encrypt arbitrary-long byte arrays containing random values (that means any values, including zeroes).
Do you know some good components (preferably free) to perform private key encryption?
I use .NET 3.5.
Note: I know this is generally considered as bad way of using asymmetric encryption (encrypting using private key and decrypting using public key), but I just need to use it that way.
Additional Explanation
Consider you have
var bytes = new byte[30] { /* ... */ };
and you want to use 2048bit RSA to ensure no one have changed anything in this array.
Normally, you would use digital signature (ie. RIPEMD160), which you then attach to the original bytes and send over to the receiver.
So, you have 30 bytes of original data, and additional 256 bytes of digital signature (because it is a 2048bit RSA), which is overall of 286 bytes. Hovewer, only 160 bits of that 256 bytes are actually hash, so there is exactly 1888 bits (236 bytes) unused.
So, my idea was this:
Take the 30 bytes of original data, attach to it the hash (20 bytes), and now encrypt these 50 bytes. You get 256 bytes long message, which is much shorter than 286 bytes, because "you were able to push the actual data inside the digital signature".
ECDSA Resources
MSDN
Eggheadcafe.com
c-plusplus.de
MSDN Blog
Wiki
DSA Resources
CodeProject
MSDN 1
MSDN 2
MSDN 3
Final Solution
If anyone is interested how I've solved this problem, I'm going to use 1024bit DSA and SHA1, which is widely supported on many different versions of Windows (Windows 2000 and newer), security is good enough (I'm not signing orders, I just need to ensure that some child can't crack the signature on his iPhone (:-D)), and the signature size is only 40 bytes long.
What you are trying to design is known as a "Signature scheme with message recovery".
Designing a new signature scheme is hard. Designing a new signature scheme with message recovery is harder. I don't know all the details about your design, but there is a good chance that it is susceptible to a chosen message attack.
One proposal for signature schemes with message recovery is RSA PSS-R. But unfortunately, this proposal is covered with a patent.
The IEEE P1363 standarization group, once discussed the addition of signature schemes with message recovery. However, I'm not sure about the current state of this effort, but it might be worth checking out.
Your Public key is a sub-set of your private key. You can use your private key as a public key as it will only use the components of the full key it requires.
In .NET both your private & public keys are stored in the RSAParameters struct. The struct contains fields for:
D
DP
DQ
Exponent
InverseQ
Modulus
P
Q
If you're at the point where the data is so small that the digital signature is huge in comparison, then you have excess signature. The solution isn't to roll your own algorithm, but to cut down what's there. You definitely don't want to try to combine a key with the hash in an amateurish way: this has been broken already, which is why we have HMAC's.
So here's the basic idea:
Create a session key using a cryptographically strong RNG.
Transmit it via PKE.
Use the session key to generate an HMAC-SHA1 (or HMAC-RIPEMD160, or whatever).
If the size of the hash is absurdly large for the given data, cut it in half by XORing the top with the bottom. Repeat as needed.
Send the data and the (possibly cut-down) hash.
The receiver uses the data and the session key to regenerate the hash and then compares it with the one transmitted (possibly after first cutting it down.)
Change session keys often.
This is a compromise between the insanity of rolling your own system and using an ill-fitting one.
I'm wide open to constructive criticism...
I get it now, after reading the comments.
The answer is: don't do it.
Cryptographic signature algorithms are not algorithms from which you can pick and choose - or modify - steps. In particular, supposing a signature sig looks something like encrypt(hash), orig + sig is not the same as encrypt(orig + hash). Further, even outdated signature algorithms like PKCS v1.5 are not as simple as encrypt(hash) in the first place.
A technique like the one you describe sacrifices security for the sake of cleverness. If you don't have the bandwidth for a 256 byte signature, then you need one of:
a different algorithm,
more bandwidth, or
a smaller key.
And if you go with (1), please be sure it's not an algorithm you made up! The simple fact is that crypto is hard.
What is a 'public key token' and how is it calculated in assembly strong names?
Regarding your question, "How is it calculated", it's an SHA1 hash.
From dot net blog:
Microsoft solves the "public key
bloat" problem by using a hash of the
strongly-named assembly's public key.
These hashes are referred to as public
key tokens, and are the low 8 bytes of
the SHA1 hash of the strongly-named
assembly's public key. SHA1 hashes are
160 bit (20 byte) hashes, and the top
12 bytes of the hash are simply
discarded in this algorithm.
You can get the PublicKeyToken from the VS Command Line by typing:
sn –T DLLName.dll
If you need to generate a public key token based on a full public key, this little static method works:
private static byte[] GetKeyTokenFromFullKey(byte[] fullKey)
{
SHA1CryptoServiceProvider csp = new SHA1CryptoServiceProvider();
byte[] hash = csp.ComputeHash(fullKey);
byte[] token = new byte[8];
for (int i = 0; i < 8; i++ )
token[i] = hash[hash.Length - (i+1)];
return token;
}
From ECMA-335:
This declaration is used to store the low 8 bytes of the SHA-1 hash of the originator’s
public key in the assembly reference, rather than the full public key.
An assembly reference can store either a full public key or an 8-byte “public key token.” Either can be used to
validate that the same private key used to sign the assembly at compile time also signed the assembly used at
runtime. Neither is required to be present, and while both can be stored, this is not useful.
[Rationale: The public key or public key token stored in an assembly reference is used to ensure that the
assembly being referenced and the assembly actually used at runtime were produced by an entity in possession
of the same private key, and can therefore be assumed to have been intended for the same purpose. While the
full public key is cryptographically safer, it requires more storage in the reference. The use of the public key
token reduces the space required to store the reference while only weakening the validation process slightly.
end rationale]
As for how the hash is calculated (I assume this may be what you're asking since the public key token is not "calculated"), from the same spec:
The CLI metadata allows the producer of an assembly to compute a cryptographic hash of that assembly (using
the SHA-1 hash function) and then to encrypt it using the RSA algorithm (see Partition I) and a public/private
key pair of the producer’s choosing. The results of this (an “SHA-1/RSA digital signature”) can then be stored
in the metadata (§25.3.3) along with the public part of the key pair required by the RSA algorithm. The
.publickey directive is used to specify the public key that was used to compute the signature. To calculate
the hash, the signature is zeroed, the hash calculated, and then the result is stored into the signature.
The Strong Name (SN) signing process uses standard hash and cipher algorithms for Strong name signing. An
SHA-1 hash over most of the PE file is generated. That hash value is RSA-signed with the SN private key. For
verification purposes the public key is stored into the PE file as well as the signed hash value.
Except for the following, all portions of the PE File are hashed:
• The Authenticode Signature entry: PE files can be authenticode signed. The authenticode
signature is contained in the 8-byte entry at offset 128 of the PE Header Data Directory
(“Certificate Table” in §25.2.3.3) and the contents of the PE File in the range specified by this
directory entry. [Note: In a conforming PE File, this entry shall be zero. end note]
• The Strong Name Blob: The 8-byte entry at offset 32 of the CLI Header (“StrongNameSignature”
in §25.3.3) and the contents of the hash data contained at this RVA in the PE File. If the 8-byte
entry is 0, there is no associated strong name signature.
• The PE Header Checksum: The 4-byte entry at offset 64 of the PE Header Windows NT-Specific
Fields (“File Checksum” in §25.2.3.2). [Note: In a conforming PE File, this entry shall be zero.
end note]
You can download the spec here for free: http://www.ecma-international.org/publications/standards/Ecma-335.htm
A public key token is used to identify the organization in a strongly named assembly. This information is added to the assembly metabase. I would assume Richard is correct about the technical way it is stored.
If you want to view the metabase of an assembly, use ILDASM. You can drill down into what is stored in the metabase in addition to seeing the IL.
It is the hash bytes of the key used to sign the assembly.
So rather than listing out hundreds of hex digits for the key, you have something simpler, but still with little risk of collisions.