Wanted Compatible AES code Encrypt/Decrypt for Iphone, Android, Windows/XP - iphone

I need to be able to send secure information to a variety of phones from Windows. I am a total novice in both iPhone and Android development, but need to create an easy to use app for each environment. Interfacing with received SMS text messages would also be nice. I would like to acquire code for AES 256 encryption for the iPhone, Android and Windows XP (and up).
Thanks
Murray

For iPhone I used AESCrypt-ObjC, and for Android use this code:
public class AESCrypt {
private final Cipher cipher;
private final SecretKeySpec key;
private AlgorithmParameterSpec spec;
public AESCrypt(String password) throws Exception
{
// hash password with SHA-256 and crop the output to 128-bit for key
MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.update(password.getBytes("UTF-8"));
byte[] keyBytes = new byte[32];
System.arraycopy(digest.digest(), 0, keyBytes, 0, keyBytes.length);
cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
key = new SecretKeySpec(keyBytes, "AES");
spec = getIV();
}
public AlgorithmParameterSpec getIV()
{
byte[] iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
IvParameterSpec ivParameterSpec;
ivParameterSpec = new IvParameterSpec(iv);
return ivParameterSpec;
}
public String encrypt(String plainText) throws Exception
{
cipher.init(Cipher.ENCRYPT_MODE, key, spec);
byte[] encrypted = cipher.doFinal(plainText.getBytes("UTF-8"));
String encryptedText = new String(Base64.encode(encrypted, Base64.DEFAULT), "UTF-8");
return encryptedText;
}
public String decrypt(String cryptedText) throws Exception
{
cipher.init(Cipher.DECRYPT_MODE, key, spec);
byte[] bytes = Base64.decode(cryptedText, Base64.DEFAULT);
byte[] decrypted = cipher.doFinal(bytes);
String decryptedText = new String(decrypted, "UTF-8");
return decryptedText;
}
}

Few important things to note while implementing AES encryption: 1. Never use plain text as encryption key. Always hash the plain text key and then use for encryption. 2. Always use Random IV (initialization vector) for encryption and decryption. True randomization is important.
I recently wrote cross platform AES encryption and decryption library for C#, iOS and Android which I have posted on Github. You can see it here - https://github.com/Pakhee/Cross-platform-AES-encryption

If you're still looking for an implementation for both devices, iPhone and Android have a look at this post. I created it together with a friend. Under the iPhone post you'll find the Android part. Both can be used by inserting them into your project like explained.
If you want to use another algorithm, you should look how they are called in iPhone and Android and change it everywhere inside the methods.

Different languages have different implementations of cryptographic classes. So I don't reckon there is a single library that will work on all platforms.
You haven't specified what language you use on Windows for your application. T
here is no easy way of encrypting and decrypting. So I suggest you at least get a solid foundcation on how encryption algorithms works with different key sizes, IV, modes of operation and padding. Also how to generate secure keys, how to transfer keys from one user to the other using asymmetric cryptography etc etc. Or do you already have the theoretical knowledge on cryptography?
For iPhone
I do not have any idea on the cryptographic classes provided in the SDK. However take a look at this question.
For Android
You have a few options here.
BouncyCastle for Java
javax.crypto package.
Here is a question you'd be interested in.
For Windows.
There are tons! For C#, and C++ and for almost all the other languages.
Also take a look at my answer for a similar question.
You should definitely study Cryptography before implementing them on your program. It would be really easy to use the built in functions but if you don't know what you are doing, you are giving your self a false sense of security and is possibly putting your customer's data on risk.

Related

How to get publicKey in RSA_encrypt key-pair generation algorithm in STRING format in flutter

I am currently working on encryption in my flutter app wherein I am using RSA key-pair generator to get public and private key using the following code-
import 'package:rsa_encrypt/rsa_encrypt.dart';
import 'package:pointycastle/api.dart' as crypto;
//Future to hold our KeyPair
Future<crypto.AsymmetricKeyPair> futureKeyPair;
//to store the KeyPair once we get data from our future
crypto.AsymmetricKeyPair keyPair;
Future<crypto.AsymmetricKeyPair<crypto.PublicKey, crypto.PrivateKey>> getKeyPair()
{
var helper = RsaKeyHelper();
return helper.computeRSAKeyPair(helper.getSecureRandom());
}
Now I want to get the keyPair.publicKey in string format but if i print keyPair.publicKey, it shows "Instance of RSA publicKey" . How can I get it in string format??
It is always best to use standardized formats when saving public keys. For RSA public keys you can store them in layers, much like a Matroesjka doll.
Encode the public key in the ASN.1 / DER format specified in the PKCS#1 RSA standard;
Encode that public key in a format called SubjectPublicKeyInfo which is part of the X.509 specifications - it indicates that this is indeed an RSA key;
Apply so called PEM "ASCII armor", which consists of a header & footer line indicating the generic SubjectPublicKeyFormat (just PUBLIC KEY), with a multi-line base 64 encoding of the public key from step 2 in between.
Sounds like a lot of work, but if you look here you'll find handy methods called encodePublicKeyToPem and parsePublicKeyFromPem that do these 3 steps for you (it actually does both 1 and 2 in the same function, which is a bit of a shame but not that important).
These keys are rather portable and are also usable by e.g. OpenSSL or PGP.

How do I sign a PDF with a Smart Card in a web context using iText?

Read through the following references:
iText Digital signature white paper, and C# examples. (specifically chapter 4) For those interested, another great and concise summary of the PDF signing process.
CAPICOM documentation.
Online examples / questions here and on iText mailing list archives, such as here and here.
Hashing code:
BouncyCastle.X509Certificate[] chain = Utils.GetSignerCertChain();
reader = Utils.GetReader();
MemoryStream stream = new MemoryStream();
using (var stamper = PdfStamper.CreateSignature(reader, stream, '\0'))
{
PdfSignatureAppearance sap = stamper.SignatureAppearance;
sap.SetVisibleSignature(
new Rectangle(36, 740, 144, 770),
reader.NumberOfPages,
"SignatureField"
);
sap.Certificate = chain[0];
sap.SignDate = DateTime.Now;
sap.Reason = "testing web context signatures";
PdfSignature pdfSignature = new PdfSignature(
PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED
);
pdfSignature.Date = new PdfDate(sap.SignDate);
pdfSignature.Reason = sap.Reason;
sap.CryptoDictionary = pdfSignature;
Dictionary<PdfName, int> exclusionSizes = new Dictionary<PdfName, int>();
exclusionSizes.Add(PdfName.CONTENTS, SIG_BUFFER * 2 + 2);
sap.PreClose(exclusionSizes);
Stream sapStream = sap.GetRangeStream();
byte[] hash = DigestAlgorithms.Digest(
sapStream,
DigestAlgorithms.SHA256
);
// is this needed?
PdfPKCS7 sgn = new PdfPKCS7(
null, chain, DigestAlgorithms.SHA256, true
);
byte[] preSigned = sgn.getAuthenticatedAttributeBytes(
hash, sap.SignDate, null, null, CryptoStandard.CMS
);
var hashedValue = Convert.ToBase64String(preSigned);
}
Just a simple test - a dummy Pdf document is created on initial page request, hash is calculated, and put in a hidden input field Base64 encoded. (the hashedValue above)
Then use CAPICOM on client-side to POST the form and get user's signed response:
PdfSignatureAppearance sap = (PdfSignatureAppearance)TempData[TEMPDATA_SAP];
PdfPKCS7 sgn = (PdfPKCS7)TempData[TEMPDATA_PKCS7];
stream = (MemoryStream)TempData[TEMPDATA_STREAM];
byte[] hash = (byte[])TempData[TEMPDATA_HASH];
byte[] originalText = (Encoding.Unicode.GetBytes(hashValue));
// Oid algorithm verified on client side
ContentInfo content = new ContentInfo(new Oid("RSA"), originalText);
SignedCms cms = new SignedCms(content, true);
cms.Decode(Convert.FromBase64String(signedValue));
// CheckSignature does not throw exception
cms.CheckSignature(true);
var encodedSignature = cms.Encode();
/* tried this too, but no effect on result
sgn.SetExternalDigest(
Convert.FromBase64String(signedValue),
null,
"RSA"
);
byte[] encodedSignature = sgn.GetEncodedPKCS7(
hash, sap.SignDate, null, null, null, CryptoStandard.CMS
);
*/
byte[] paddedSignature = new byte[SIG_BUFFER];
Array.Copy(encodedSignature, 0, paddedSignature, 0, encodedSignature.Length);
var pdfDictionary = new PdfDictionary();
pdfDictionary.Put(
PdfName.CONTENTS,
new PdfString(paddedSignature).SetHexWriting(true)
);
sap.Close(pdfDictionary);
So right now I'm not sure if I'm messing up hashing part, signature part, or both. In signature code snippet above and in client code (not shown) I'm calling what I think is signature verification code, but that may be wrong too, since this is a first for me. Get the infamous "Document has been altered or corrupted since it was signed" invalid signature message when opening the PDF.
Client-side code (not authored by me) can be found here. Source has a variable naming error, which was corrected. For reference, CAPICOM documentation says signed response is in PKCS#7 format.
EDIT 2015-03-12:
After some nice pointers from #mkl and more research, it seems CAPICOM is practicably unusable in this scenario. Although not documented clearly, (what else is new?) according to here and here, CAPICOM expects a utf16 string (Encoding.Unicode in .NET) as input to create a digital signature. From there it either pads or truncates (depending which source in previous sentence in correct) whatever data it receives if the length is an odd number. I.e. signature creation will ALWAYS FAIL if the Stream returned by PdfSignatureAppearance.GetRangeStream() has a length that is an odd number. Maybe I should create an I'm lucky option: sign if ranged stream length is even, and throw an InvalidOperationException if odd. (sad attempt at humor)
For reference, here's the test project.
EDIT 2015-03-25:
To close the loop on this, here's a link to a VS 2013 ASP.NET MVC project. May not the be best way, but it does provide a fully working solution to the problem. Because of CAPICOM's strange and inflexible signing implementation, as described above, knew a possible solution would potentially require a second pass and a way to inject an extra byte if the return value of PdfSignatureAppearance.GetRangeStream() (again, Stream.Length) is an odd number. I was going to try the long and hard way by padding the PDF content, but luckily a co-worker found it was much easier to pad PdfSignatureAppearance.Reason. Requiring a second pass to do something with iText[Sharp], is not unprecedented - e.g. adding page x of y for a document page header/footer.
Use of PdfPkcs7
The server-side code contains this block after the calculation of the range stream digest and before forwarding data to the web page:
PdfPKCS7 sgn = new PdfPKCS7(
null, chain, DigestAlgorithms.SHA256, true
);
byte[] preSigned = sgn.getAuthenticatedAttributeBytes(
hash, sap.SignDate, null, null, CryptoStandard.CMS
);
var hashedValue = Convert.ToBase64String(preSigned);
In the case at hand this is not necessary. It is needed only if the external signing API you use merely returns a signed digest; in that case the PdfPKCS7 instance builds the CMS/PKCS#7 signature container. You, on the other hand, use an API for which you know
CAPICOM documentation says signed response is in PKCS#7 format.
Thus, you don't need and (more to the point) must not use the PdfPKCS7 instance.
What does sign.js sign
The content of the server-side hash variable already is the hash digest value of the data to sign. Thus, the frontend, i.e. the sign.js used there, must not hash it again to get the message digest attribute value to put into the signature.
But sign.js signing methods for IE eventually execute
var signedData = new ActiveXObject("CAPICOM.SignedData");
// Set the data that we want to sign
signedData.Content = src;
SignedData.Content, on the other hand, is documented as
Content Read/write Data to be signed.
(msdn: "SignedData object")
So the hash from the backend is used as data to be signed and not as hash of the data to be signed, you indeed hash twice and so have the wrong hash value there.
Thus, it looks like you have to transmit the whole ranged stream which is not really practical...
"But there used to be signing samples using CAPICOM..."
Indeed some old iTextSharp (version 4.x) signing example used CAPICOM. But that code only worked because it created signatures of PDF signature type adbe.pkcs7.sha1 for which a SHA1 hash of the ranged stream indeed is the data embedded in and signed by the PKCS#7 signature.
This is no real option anymore because
it requires the use of SHA1 which in serious contexts is invalid, and
its use has been discouraged at least since ISO 32000-1 (2008) and will be officially deprecated in ISO 32000-2 (under development).

Sign PDF using an external service and iText

I have this scenario.
I have an application that generates a PDF, and that needs to be signed.
We have not the certificates to sign the document, because they're in a HSM, and the only way we could make use of the certificates is using a webservice.
This webservice, offers two options, send the PDF document, and it returns a signed pdf, or send a hash that will be signed.
The first option, is not viable, because the PDF is signed without a timestamp (this is a very important requisite), so the second option is chosen.
This is our code, first, we get the signature appearance, and calculate the hash:
PdfReader reader = new PdfReader(Base64.decode(pdfB64));
reader.setAppendable(true);
baos = new ByteArrayOutputStream();
PdfStamper stamper = PdfStamper.createSignature(reader, baos, '\0', null, true);
appearance = stamper.getSignatureAppearance();
appearance.setCrypto(null, chain, null, PdfSignatureAppearance.SELF_SIGNED);
appearance.setVisibleSignature("Representant");
cal = Calendar.getInstance();
PdfDictionary dic = new PdfDictionary();
dic.put(PdfName.TYPE, PdfName.SIG);
dic.put(PdfName.FILTER, PdfName.ADOBE_PPKLITE);
dic.put(PdfName.SUBFILTER, new PdfName("adbe.pkcs7.detached"));
dic.put(PdfName.M, new PdfDate(cal));
appearance.setCryptoDictionary(dic);
HashMap<PdfName, Integer> exc = new HashMap<PdfName, Integer>();
exc.put(PdfName.CONTENTS, Integer.valueOf(reservedSpace.intValue() * 2 + 2));
appearance.setCertificationLevel(1);
appearance.preClose(exc);
AbstractChecksum checksum = JacksumAPI.getChecksumInstance("sha1");
checksum.reset();
checksum.update(Utils.streamToByteArray(appearance.getRangeStream()));
hash = checksum.getByteArray();
In this point, we have the hash code of the document. Then we send the hash to the webservice, and we get the signed hash code.
Finally, we put the signed hash to the PDF:
byte[] paddedSig = new byte[reservedSpace.intValue()];
System.arraycopy(signedHash, 0, paddedSig, 0, signedHash.length);
PdfDictionary dic = new PdfDictionary();
dic.put(PdfName.CONTENTS, new PdfString(paddedSig).setHexWriting(true));
appearance.close(dic);
byte[] pdf = baos.toByteArray();
In this point, we get a PDF signed, but with an invalid signature. Adobe says that "Document has been altered or corrupted since it was signed".
I think that we make something wrong in the process, and we don't know exactly what could be.
We appreciate help on this, or an alternative way to do that.
Thanks.
EDITED
As suggested by mkl, I have followed the 4.3.3 section of this book Digital Signatures for PDF documents, and my code now what that follows:
The first part, when we calculate the hash:
PdfReader reader = new PdfReader(Base64.decode(pdfB64));
reader.setAppendable(true);
baos = new ByteArrayOutputStream();
PdfStamper stamper = PdfStamper.createSignature(reader, baos, '\0');
appearance = stamper.getSignatureAppearance();
appearance.setReason("Test");
appearance.setLocation("A casa de la caputeta");
appearance.setVisibleSignature("TMAQ-TSR[0].Pagina1[0].DadesSignatura[0].Representant[0]");
appearance.setCertificate(chain[0]);
PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
dic.setReason(appearance.getReason());
dic.setLocation(appearance.getLocation());
dic.setContact(appearance.getContact());
dic.setDate(new PdfDate(appearance.getSignDate()));
appearance.setCryptoDictionary(dic);
HashMap<PdfName, Integer> exc = new HashMap<PdfName, Integer>();
exc.put(PdfName.CONTENTS, new Integer(reservedSpace.intValue() * 2 + 2));
appearance.preClose(exc);
ExternalDigest externalDigest = new ExternalDigest()
{
public MessageDigest getMessageDigest(String hashAlgorithm) throws GeneralSecurityException
{
return DigestAlgorithms.getMessageDigest(hashAlgorithm, null);
}
};
sgn = new PdfPKCS7(null, chain, "SHA256", null, externalDigest, false);
InputStream data = appearance.getRangeStream();
hash = DigestAlgorithms.digest(data, externalDigest.getMessageDigest("SHA256"));
cal = Calendar.getInstance();
byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, cal, null, null, CryptoStandard.CMS);
sh = MessageDigest.getInstance("SHA256", "BC").digest(sh);
hashPdf = new String(Base64.encode(sh));
And in the second part, we get the signed hash, and we put that into the PDF:
sgn.setExternalDigest(Base64.decode(hashSignat), null, "RSA");
byte[] encodedSign = sgn.getEncodedPKCS7(hash, cal, null, null, null, CryptoStandard.CMS);
byte[] paddedSig = new byte[reservedSpace.intValue()];
System.arraycopy(encodedSign, 0, paddedSig, 0, encodedSign.length);
PdfDictionary dic2 = new PdfDictionary();
dic2.put(PdfName.CONTENTS, new PdfString(paddedSig).setHexWriting(true));
appearance.close(dic2);
byte[] pdf = baos.toByteArray();
Now, Adobe raises a Internal Cryptographic library error. Error Code: 0x2726, when we try to validate the signature.
If the web service returned a mere signed hash
In this point, we have the hash code of the document. Then we send the hash to the webservice, and we get the signed hash code.
Finally, we put the signed hash to the PDF:
If the webservice merely returns a signed hash, then your PDF signature is incorrect: You set the signature SubFilter to adbe.pkcs7.detached. This implies that the signature Contents have to contain a full-blown PKCS#7 signature container, not merely a signed hash.
You might want to download Digital Signatures for PDF documents, A White Paper by Bruno Lowagie (iText Software) on creating and verifying digital PDF signatures using iText. It especially contains a section "4.3 Client/server architectures for signing" which should encompass your use cases.
But the web service returns a full-fledged CMS signature container
Following to the explanation above, the OP started using code from section 4.3.3 of the above-mentioned white paper which is intended for signing using externally generated signed hashes. As this also resulted in a signed document Adobe Reader was not happy with, he provided a sample document created with this new code.
Analysis of the sample showed that the CMS signature container embedded in the document contained another CMS signature container where there should have been the signature bytes (the signed hash) for the signed attributes:
2417 13: SEQUENCE {
2419 9: OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
2430 0: NULL
: }
2432 5387: OCTET STRING, encapsulates {
2436 NDEF: SEQUENCE {
2438 9: OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2)
2449 NDEF: [0] {
2451 NDEF: SEQUENCE {
(The OCTET STRING following the signature algorithm should contain the signature bytes and not embed another SignedData structure.)
This indicates that the web service indeed already returns a full-fledged CMS container.
For such a scenario the original code looked quite ok. The issue might be due to a detail like the use of a wrong hashing algorithm (the original code hashed using SHA1).
A possible issue: BER encoding
The CMS signature container from the web service embedded in the CMS container generated by iText from the first sample provided by the OP hints at a possible issue: Looking at the ASN.1 dump above the sizes of the outer structures in the embedded CMS container are often NDEF.
This indicates that these outer structures are created using the less strict BER (Basic encoding Rules), not the more strict DER (Distinguished Encoding Rules) because the BER option to start a structure without stating its size is forbidden in DER.
The CMS specification (RFC 3852) referenced from the PDF specification does allow any BER encoding for the outer structures of the container, the PDF specification on the other hand requires:
the value of Contents shall be a DER-encoded PKCS#7 binary data
object containing the signature. The PKCS#7 object shall conform to RFC3852 Cryptographic Message Syntax.
Strictly speaking, therefore, signature containers embedded in PDFs are required to be DER encoded all over.
As far as I know no PDF signature validator rejects such signatures as long as the signature container DER-encodes certain pivotal elements. Concerning future tools such signatures are a possible point of failure, though.
After much debugging, we finally found the problem.
For some mysterious reason, the method that generates the hash of the document, was executed twice, invalidating the first hash (which we use to send to the service).
After a refactoring work of the code, the original code worked correctly.
Very thanks to all people that help me, especially mkl.

How to use strong encryption for password field using grails with postgresql database?

I had to migrate a legacy database with clear text password to a PostgresSQL database. I've looked up what's the best way to encrypt password in a database and found the pgcrypto extension with slow algorithm. (see pgcrypto documentation for 8.4)
The migration is done for data and everything is working well.
Now I have to write a CRUD application to handle this data.
I'm wondering what's the best way to use this strong encryption with grails ?
In my model, I've used the afterInsert event to handle this :
def afterInsert() {
Compte.executeUpdate("update Compte set hashpass=crypt(hashpass, gen_salt('bf', 8)) where id = (:compteId)", [compteId: this.id])
}
I guess that I should also check if the hashpass field is modified whenever the model is saved. But before that, is there another (best) way to achieve my goal ?
Edit : I cannot use the Spring Security bcrypt plugin here. The CRUD application that I'm writing use SSO CAS so I don't need such a plugin. The CRUD application manages accounts for another application that I don't own. I just need to create a new account, modify or delete an existing one. This is very simple. The tricky part is to hack grails so that it takes into account the password field and use a specific sql to store it to a postgreSQL database.
Edit 2 :
I've come up with the following code but it doesn't work
def beforeInsert() {
hashpass = encodePassword(hashpass);
}
def encodePassword(cleartextpwd) {
// create a key generator based upon the Blowfish cipher
KeyGenerator keygenerator = KeyGenerator.getInstance("Blowfish");
// create a key
SecretKey secretkey = keygenerator.generateKey();
// create a cipher based upon Blowfish
Cipher cipher = Cipher.getInstance(ALGORITHM);
// initialise cipher to with secret key
cipher.init(Cipher.ENCRYPT_MODE, secretkey);
// get the text to encrypt
String inputText = cleartextpwd;
// encrypt message
byte[] encrypted = cipher.doFinal(inputText.getBytes("UTF-8"));
return Base64.encodeBase64String(encrypted);
}
I get a hash that is not a blowfish hash (beginning with $2a$08$ )
Edit 3 :
I've finally came up with a cleaner grails solution after reading this wiki page : grails.org/Simple+Dynamic+Password+Codec (not enough reputation to put more than 2 links so add http:// before) and the bug report jira.grails.org/browse/GRAILS-3620
Following advice from #lukelazarovic, I've also used the algorithm from the spring security plugin.
Here is my password encoder to put into grails/utils :
import grails.plugin.springsecurity.authentication.encoding.BCryptPasswordEncoder;
class BlowfishCodec {
static encode(target) {
// TODO need to put the logcount = 8 in configuration file
return new BCryptPasswordEncoder(8).encodePassword(
target, null)
}
}
I've updated my Compte model to call my password encoder before saving / updating the data :
def beforeInsert() {
hashpass = hashpass.encodeAsBlowfish();
}
def beforeUpdate() {
if(isDirty('hashpass')) {
hashpass = hashpass.encodeAsBlowfish();
}
}
The tricky part is to hack grails so that it takes into account the
password field and use a specific sql to store it to a postgreSQL
database.
Is there any particular reason to do the hashing in database?
IMHO it's better to hash the password in Grails, therefore have a code that is not database-specific and easier to read.
For hashing passwords using Blowfish algorithm using Java or Groovy see Encryption with BlowFish in Java
The resulting hash begins with algorithm specification, iteration count and salt, separated with dollar sign - '$'. So the hash may look like "$2a$08$saltCharacters" where 2a is a algorithm, 08 is iteration count, then follows salt and after salt is the hash itself.
For broader explanation see http://www.techrepublic.com/blog/australian-technology/securing-passwords-with-blowfish. Don't mind that it concerns to Blowfish in PHP, the principles applies for Java or Groovy as well.

Determine certificate key type (RSA vs EC) in .NET or BouncyCastle?

Currently we have a routine that Signs a byte[] given a certificate (and it's private key). However, the type of certificate/keys is hardcoded as "Certificate with RSA keys". That code is :
public byte[] Sign(byte[] bytesToSign, bool fOAEP, X509Certificate2 certificate)
{
using (RSACryptoServiceProvider provider = new RSACryptoServiceProvider())
{
// HACK: Round-trip the key to XML and back, to get provider type working
// as 'Microsoft Enhanced RSA and AES Cryptographic Provider' (for
// SHA256/SHA512 signing hash) instead of 'Microsoft Enhanced
// Cryptographic Provider v1.0' (that limits us to SHA1)
string publicKeyXml = certificate.PrivateKey.ToXmlString(true);
provider.FromXmlString(publicKeyXml);
// We use the private key to sign.
return provider.SignData(bytesToSign, CryptoConfig.MapNameToOID("SHA512"));
}
}
We would like to make it more flexible where if the certificate uses RSA keys, we process it one way but if it uses EC keys, then we process it differently. Basically the Crypto Service Provider type would be of a different type.
So the core question is:
Given a certificate with public+private keys (for signing) OR a certificate with just public keys (for verifying), how do you determine the types of keys used by the certificate?
I'm open to standard .NET libs or even BouncyCastle.Org libs.
You can check key type (algorithm) via certificate.PublicKey.Oid.
Here you can see supported by Microsoft OIDs: http://msdn.microsoft.com/en-us/library/ff635835.aspx
Other OIDs can be checked at oid-info.com