How to sign in case of using more then 1 certificate - cosign-api

I have more than 1 certificate, how to indicate the default one to use for signing in my SAPI code.
My code written in vb6.

The most simple way to define a default certificate is by providing the serial ID of the preferred certificate as part of the configuration values (using ConfigurationValueSet SAPI function).
Another way to do it is to enumerate the certificates using CertificatesEnumInit and CertificatesEnumCont functions and then set the chosen one with the CertificateSetDefault function.

Related

Digital Signature With TSA Timestamping adding certificates in chain in TSA response PDF Box giving error “not enough space to write signature”

I have created digital signature with timestamping the signature via TSA. In this I have added certificates to build chain in TSA response for building chain this works fine and signature also created, but while embedding this signature in pdf using PDF box API for Java it gives error not enough space to write signature. Is there any configuration available in PDF box to handle signature size?
Any help would be appreciated.
I assume you're using an embedded timestamp as in the CreateEmbeddedTimeStamp.java example, so you're using the space of the existing signature. That one is fixed, so you need to make it large enough:
signatureOptions.setPreferredSignatureSize(...);
with a number higher than the default (0x2500). The SignatureOptions object can be passed in the document.addSignature() call.

VB.NET SECURE LOGIN SERVERSIDE + CLIENTSIDE

ClientSide Sending Key Example: tabc-xkaf-gaga-gtax to the Server
Server Checks if Key Exists in Database if YES then return TRUE as Response
ClientSide IF RESPONSE = TRUE THEN
OPEN FORM1
But thats not a Secure way to do it cause they can change the Response of the ServerSide check and then get the Product for free cause it will open Form1 anyone has a better way to do it?
Signed server side response and verify server response at client side to check whether response was altered or not.
Refer this article for how to digitally signed and verify
Moreover this will be a typical solution and suit for very complex security .
For simple solution, You can send hash of response along with server response and convert response to hash at client side. compare both hash , if they match it means response was not changed.
As you indicated, professional attackers can see and decode VB.Net applications, and hence, as an initial conclusion, you cannot reliably protect your code. In the first step, you must encrypt your code by using several encryption techniques such as the one mentioned by #Always_a_learner. However, this will not 100% protect your code from reverse-engineering (A good discussion could be found here).
A good trick in such cases is to make some intentional dependencies. For example, some core calculations should be done by the server (if possible) and only the result should be returned to the client. More explanation, for core calculations, the client should send a request to the server, and the server first verifies the requester (the sender) validity state, and if she is a valid user, then runs calculations and returns results to the user.
This solution is fine only if you can trade-off between speed and security.

How can one encrypt content using RSA for Chilkat in C# and decrypt it in Java?

UPDATE
I see that lots of people find my question too long (because there is lots to explain), read the first sentence and then just think that I'm going on the worst tangent possible without seeing the entire question. If the question isn't clear enough please let me know. I'm trying to condense it in the simplest way and not to cause any confusion.
The reason for the public key decryption is to achieve a form of digital signing where the recipient decrypts the encrypted content to reveal a hash value. I didn't see the need to mention this in the question as I wanted to find out how to perform this operation in its basic form. However to avoid any further concerns and warnings around what RSA is all about and that public key decryption is bad, I updated my question with that disclaimer.
BACKGROUND
I have written a C# application that uses the Chilkat's RSA library to take content and encrypt it using a personal Private Key.
Then I would like to use a public website to allow someone to decrypt that very content (that's encrypted) by using an associated public key.
Now, I found a 3rd party website (and there are not a lot of them, BTW) that allows you to decrypt content using a RSA public key (https://www.devglan.com/online-tools/rsa-encryption-decryption).
Unfortunately when I try to use it, I get a "Decrypt error".
Here is a sample setup. I have generated my own personal Public & Private Key pairs. In my C# application, I'm taking a string and encrypting it with a private key and encoding it using Base64.
const string originalContent = "This !s original c0nt3nt";
var rsa = new Chilkat.Rsa();
rsa.GenerateKey(2048);
var encryptedBytes = rsa.EncryptBytes(Encoding.UTF8.GetBytes(originalContent), true);
var encryptedEncodedString = Convert.ToBase64String(encryptedBytes);
Console.WriteLine($"Encrypted:{Environment.NewLine}{encryptedEncodedString}");
Console.WriteLine();
var privateKeyBytes = rsa.ExportPrivateKeyObj().GetPkcs8();
var privateKeyEncodedString = Convert.ToBase64String(privateKeyBytes);
Console.WriteLine($"Private Key:{Environment.NewLine}{privateKeyEncodedString}");
Console.WriteLine();
var publicKeyBytes = rsa.ExportPublicKeyObj().GetDer(false);
var publicKeyEncodedString = Convert.ToBase64String(publicKeyBytes);
Console.WriteLine($"Public Key:{Environment.NewLine}{publicKeyEncodedString}");
Console.WriteLine();
var decyptedContentBytes = rsa.DecryptBytes(encryptedBytes, false);
var decryptedContentString = Encoding.UTF8.GetString(decyptedContentBytes);
Console.WriteLine($"Decrypted:{Environment.NewLine}{decryptedContentString}");
Console.WriteLine();
Console.WriteLine("Press ENTER to quit");
Console.ReadLine();
This sample console app will write out all the necessary information needed to use for the next part of the process and to demonstrate that in principle it works as expected.
Example:
Here are the sample values from the console window:
ENCRYPTED CONTENT
H5JTsGhune1n3WWSPjwVJuUwp70Hsh1Ojaa0NFCVyq0qMjVPMxnknexOG/+HZDrIYsZM7EnPulpmihJk4QyLM8T2KNQIhbWuMHvzgHYlcPJdXpGZhAxwfklL4HP0iRUUXJBsJcS/2XoUDZ6elUoMIFY9cDB4O+WFxKS/5vzLEukTLbQ3aEBNg3xaf9fg12F8LcMxZ3GDsk0W9b6oJci09NTxXd6KKes0RM1hnOhw6bu0U33ZLF3sa0nH9Kdf8w23PoKc/tl12Jsa8N1A4OjaT5910UF8FRH6OkAbNKnxqXcL7+V4HVuHchi3ghuFivAW57boLeHr7OG7wOEC/gfPOw==
PRIVATE KEY
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC8xYcNXckXf1X4Kd6qE5c7pddfWdKo71mcwZWskuaq+wq3FTcCTAedo/Vcx8Vxn+RMn5XE7QCDzcAAN0K/BzQsoU81myRzZ+bKP+TJ5HH0jClCUMj+ideEm0fay873jnbG0hKEOJPVxPWwKq3jvDLLmWrdgvd/UiDStDm286SFKfMlLWkSw8YIc5nXsthAgP0hv8Nj7UDKvTEG5o3boTuhG1JQARCEXP0fTdIiv0cEFlSN3KkgF4KDf32Vt2x57N/+PJXpQvcECkLwPpBAq/aM0qbtgeiILxavfBJRwQ5zXDUmZHepvSjK6KIYQsTavQQLDXnFKuXa2fxOJHIlys6pAgMBAAECggEBAI0ZMBtDkL2phj7aPP7vaclB6rvwzc9MKLVM1W2K2DPRNW8nwlhLMB4aoZnaELEfjGvhlPb/F7VtIyiGJbPX1J3PbP9qmVJRxWZDX+WwhaT+5xAUhkgMDDWoQ4s9b9QGfq2Z9BE0oPvWHraxEAz7bRRV9lTgQdK/Np2H7OPdNYn6SW8qVgAukgTBqVno4VDbC34bJwal0e63oBFFfensWlhPtDUQB/uQX7UiRfEkxL+CNuqVLDoAeXWmSVWOPlDTKVu1y1bzfA+WMOKHm1ndq21I07TUPf9FcgYdKf4yKpWvMfVeDev6Oo/2mlac+vrJO571S+h4a5m79jUhCeJwX4kCgYEA7q5hrNtMbErA6dgEOG+KpFTaeqbknwtcykVApEvHt4LKULedAvwkORu65acKFYkxbMt19Fx7ligGxg0yOQRWX1BXK1XOCo9eYOjvOVlbRqBywLIbegehoZQ0LoSsdRcOvFq7EbMV3BaxCmxgpnrCZ75VaCYUMzylIduPWKeT9xcCgYEAyngNIIgsXfpCI+HHILNpprFfS2JBBGPx8N/d9cXahKCJhxrMe8K64CSMyxTwum5DXjJnbE4QBsoowRZTCEF6JUBagRM/pQrVX/CK//oyUUaa5+1S/0OxlUevXR7TD6gcpGNEdPjruc+gZzhfKFuWh+V9mJQUviqm3RjAcEdHAD8CgYBL0kOfGM8vO5QK9R9qGiztxTLecbQAvihM7TD6wEQCjN7eQ2Xyc8zCA4gcujKe4sU7rWqcJODxs2drdPe2WyVhA/GdB5X7js3JdVXBXxx61C9//VRzMIds/9qPyH/MdnWs6hmxJrXUA7Vb/U+6sxacxD73ZdlW6XX/ynLAFAQSIwKBgQCk4i12j87p3ZMdW5HprJJeoNYFMwfVxnrSec1tiGoTVhWJxCZAp22+eaV7ARumB4OvY4bcKZpdnSahUEfgUkphqc3Kjd1nz7HCxsa7/YoarFAcjiXoIb2t30oNoLurZXGl4f1u8QQvNsnfJYZA/I1TMG4e4oEd+OgY6D5XcYR9ywKBgGdaZmoBieiw0NkbijjgQZ0WILDmrIYdsSp4HMp6XDeVvdMb/qYg2jTnvVyqMSb8NdfCOB0GT19r1isQX9RnUgxPikJbVLj8WjAQjHT28mtmRn+Ju/3KT75RJ/LHY3SySNMOgTW75X2u8v0ELdEiiOmc/vTkCYoS/oqp92ELjT1Y
PUBLIC KEY
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvMWHDV3JF39V+CneqhOXO6XXX1nSqO9ZnMGVrJLmqvsKtxU3AkwHnaP1XMfFcZ/kTJ+VxO0Ag83AADdCvwc0LKFPNZskc2fmyj/kyeRx9IwpQlDI/onXhJtH2svO9452xtIShDiT1cT1sCqt47wyy5lq3YL3f1Ig0rQ5tvOkhSnzJS1pEsPGCHOZ17LYQID9Ib/DY+1Ayr0xBuaN26E7oRtSUAEQhFz9H03SIr9HBBZUjdypIBeCg399lbdseezf/jyV6UL3BApC8D6QQKv2jNKm7YHoiC8Wr3wSUcEOc1w1JmR3qb0oyuiiGELE2r0ECw15xSrl2tn8TiRyJcrOqQIDAQAB
WEBSITE PUBLIC KEY DECRYPTION ATTEMPT
Now, when I go to the website (mentioned above) I paste in my encrypted content in the encrypted content text block and I paste my public key that I generated in the text block underneath it and set the RSA Key Type to Public Key. But it fails.
SECOND ATTEMPT
But...
I have done some troubleshooting by taking my personal Private & Public keys that I generated and I use the website to perform the encryption & decryption with my keys and I'm able to encrypt my string and decrypt that encrypted content successfully which leads me to believe that somehow my Chilkat encryption setup is not fully aligned with the one that the website uses.
WHAT I NOTICED
So I started reading what the website had to offer and the author of the page posted an explanation on how to accomplish this (https://www.devglan.com/java8/rsa-encryption-decryption-java) which uses the Java RSA libraries under the hood. Apparently, there are two Java RSA ciphers that can be used "RSA" and "RSA/ECB/PKCS1Padding".
I am not so familiar with the Java libs and I know enough of cryptography to know how to get things done but there are lots of technical aspects that are still unclear to me as to help me figure out where to go next.
QUESTION
My question is, is there anything in Chilkat that I need to setup so that it can encrypt content that would allow a Java application (like the website link posted above) to be able to decrypt? (of course Chilkat needs to be able to decrypt it as well)
A message that has been encrypted with the private key using the Chilkat-library cannot be decrypted with the public key using Java (at least not with the standard SunJCE-provider) or the java-based web-site, since different padding variants are used on both sides.
The prerequisite for a successful decryption is that both encryption and decryption use the same padding variant. The same applies to signing and verification.
There are two variants of the PKCS1-v1.5-padding described in RFC8017: One is RSAES-PKCS1-v1_5, which is used in the context of encryption and decryption, and the other is RSASSA-PKCS1-v1_5, which is used in the context of signing and verifying. RSAES-PKCS1-v1_5 is non-deterministic, i.e. repeated encryption of the same plaintext with the same key always generates different ciphertexts. RSASSA-PKCS1-v1_5 is deterministic, that is, it always generates the same ciphertext under the mentioned conditions.
Since the padding variant depends on the respective platform/library, a general statement is not possible. However, for the Chilkat-library and Java (standard SunJCE provider) the following applies (PKCS1-v1.5-padding assumed):
The methods that Chilkat provides in the context of encryption/decryption use RSAES-PKCS1-v1_5 regardless of whether the public or private key is used for encryption. Analog methods also exist in the context of signing/verifying. These use RSASSA-PKCS1-v1_5.
To check this, the padding variant can be determined by setting the Chilkat.Rsa#NoUnpad flag to true, so that the padding is not removed during decryption. Another option for a test is to repeatedly encrypt the same plaintext with the same key. Since RSAES-PKCS1-v1_5 is probabilistic, different ciphertexts are generated each time.
In Java, the Cipher-class determines which padding variant is used based on the mode (encryption or decryption) and the key type used (private or public). For encryption with the public key and decryption with the private key, RSAES-PKCS1-v1_5 is used. For encryption with the private key and decryption with the public key, RSASSA-PKCS1-v1_5 is used. For signing/verifying, Java provides the Signature-class which uses RSASSA-PKCS1-v1_5.
To check this, proceed as described above. In Java, you can prevent the padding from being removed with RSA/ECB/NoPadding during decryption.
Since in the context of encryption/decryption the public key is used for encryption and the private key is used for decryption, and dedicated classes or methods are used in the context of signing/verifying, there are no or few use cases for direct encryption with the private key and decryption with the public key. Furthermore or maybe because of that these processes are not uniformly implemented in the libraries as you can see in the example of the Chilkat-library and Java.
Altogether three cases can be distinguished for the Chilkat-library and Java:
Within the same library/language, encryption can be performed with the public or private key and decryption with the respective counterpart. For this reason the encryption and decryption on the web site (using Java) works in the posted example Second Attempt: Both the encryption with the private key and the decryption with the public key use RSASSA-PKCS1-v1_5.
If in the Chilkat-code the public key is used for encryption and in Java the private key is used for decryption, RSAES-PKCS1-v1_5 is used for both encryption and decryption, which is why decryption works.
However, if in the Chilkat-code the private key is used for encryption and in Java the public key is used for decryption, RSAES-PKCS1-v1_5 is used for encryption and RSASSA-PKCS1-v1_5 is used for decryption. Both padding variants therefore differ and decryption fails. This corresponds to the scenario described in the question.
After this explanation now to your question: My question is, is there anything in Chilkat that I need to setup so that it can encrypt content that would allow a Java application (like the website link posted above) to be able to decrypt? Since the Java-code uses RSASSA-PKCS1-v1_5 for decryption with a public key, it would be necessary for compatibility to change the padding variant in the Chilkat-code from RSAES-PKCS1-v1_5 to RSASSA-PKCS1-v1_5 in the context of encryption/decryption. If you look at Chilkat's RSA-methods, it seems that this is not intended, but that the logic for determining the padding variant is hard coded (as probably with most libraries). You can only choose between PKCS1-v1.5-padding and OAEP for padding. This means that a message encrypted with the private key using the Chilkat-code cannot be decrypted with the public key in Java or on the website.
What are the alternatives? According to the question, the goal is: The reason for the public key decryption is to achieve a form of digital signing where the recipient decrypts the encrypted content to reveal a hash value.
Here it would be a good idea to create a standard signature on the Chilkat-side, e.g. with signBytes. The hash of the data is created automatically and RSASSA-PKCS1-v1_5 is used as padding variant (if the data are already hashed, the method signHash can be used). On the Java-side, this signature can be verified. Alternatively, the signature can be decrypted with the public key, which allows the hash value to be determined, since Java uses the padding variant RSASSA-PKCS1-v1_5 in both cases. Decryption is also possible on the web site, but the decrypted data are not displayed properly because they are only given as a string (which does not produce any meaningful output because of the arbitrary byte-sequences in a hash) and the encoding cannot be changed to hexadecimal or Base64.
Another possibility might be to use Chilkat on the Java-side as well. Probably Chilkat uses a uniform logic across platforms (which I didn't verify however).
I'm going to (hopefully) answer this question after only reading the 1st part of it. I got to the point where you wrote "... I'm taking a string and encrypting it with a private key ...", and this raised the red flag.
Public key encryption should be where you encrypt using the recipient's public key. The private key is used to decrypt. The point of encryption is that only the intended recipient can decrypt and view the message. With public/private key pairs, you can provide your public key to anybody, but you are in sole possession of your private key. Therefore, anybody can use your public key to encrypt a message intended for you, but you are the only one who can decrypt. This makes sense.
Signing is the opposite: You use your private key to sign, and anybody can verify using your public key. A signature can optionally contain the signed data, so that the act of verifying the signature also extracts the original data. Thus, you verify that (1) the data could only have been signed by the holder of the private key, (2) the data was not modified, and (3) you recover the original data.
Chilkat's API provides the ability to use the public/private keys in the opposite way, which doesn't make any sense, but was needed because there are systems "out there" that do things that make no sense, and Chilkat was needed to perform the opposite. (It makes no sense to encrypt something that anybody can decrypt.)
I think the code behind the devglan website is not capable of doing the RSA encrypt/decrypt in the opposite way. You would need to encrypt using your public key, and then give your private key to the other person.
Or.. you could instead create an "opaque signature" using Chilkat, which is a signature containing the data, and then find the devglan online tool to verify/extract the data from the PKCS7 signature (if the devglan tool exists). This way you can keep your private key and give the public key to the recipient.
Finally.. it seems to me that you're really treating the public/private key as a shared secret -- i.e. a secret only shared between sender and receiver. In that case, why bother using RSA at all? (Remember, RSA is only for encrypting/decrypting small amounts of data. The max number of bytes you can encrypt is equal to the key size minus some overhead. So if you have a 2048-bit key, then you can maximally encrypt 2048/8 bytes minus the overhead used in padding, which is on the order of 20 bytes or so.) If semantically you just have a shared secret, then you might simplify and use symmetric encryption (AES) where the secret key is just a random bunch of bytes and you have no data size limit.

Parsing an X509 Certificate

I currently need to parse the CommonName from a packet. I have code that works up to a point, however am having trouble skipping over the "issuer" member of a Certificate record for TLSv1.2. I have done research on the format of the SSL records and have investigated the dump via wireshark. I've found the format is generally - Length, followed by the data. However when trying to find the issue length, I cannot seem to get it, and is inconsistent with the bytes presented. Any ideas..or a better way to skip over the issuer field, and go directly to the "subject" of an TLS 1.2 record. Coded in C..Thank you for useful responses.
You need to understand ASN.1. Go read this book (it is a free download). Once you have read and understood it, you can write your decoder, following the ASN.1 specification for certificates. This is doable, but requires great implementation care. In fact, this is a bad idea unless you are a demi-god of C programming.
Alternatively, use some library that already knows how to decode a certificate. Typically, OpenSSL.

Can one encrypt with a private key/decrypt with a public key?

[Disclaimer: I know, if you know anything about crypto you're probably about to tell me why I'm doing it wrong - I've done enough Googling to know this seems to be the typical response.]
Suppose the following: you have a central authority that wants to issue login cookies for a given domain. On this domain, you don't necessarily trust everyone, but you have a few key end-points who should be able to read the cookie. I say a few, but in practice this number of "trusted" partners may be large. The cookie doesn't contain much information - a username, a timestamp, an expiry, a random number. It should remain small of course, for performance reasons, even after encryption (within reason). Now, there are two security issues:
1) We don't trust every webserver on this domain with user data. For this reason, the ability to read the cookie should be restricted to these trusted partners.
2) While we trust these partners to protect our user's data, we'd still like the central point of authority to be unforgeable (again, within reason).
Now, if we generate a private RSA key for the authority and keep it secret, and distribute the public key only to the "trusted partners", we should be able to encrypt with the private key and have it readable by anyone with the public key. What I'm unclear on is, would it still be necessary to sign the message, or would the act of decrypting be evidence that it was generated with the private key? Is this any way in which this scheme would be better or worse than disseminating a symmetric key to all parties involved and using that to encrypt, while using the private key merely to sign? And of course feel free to tell me all the ways this is a stupid idea, but bear in mind that practical arguments will probably be more convincing than rehashing Alice and Bob.
Oh, and implementation pointers would be welcome, though one can find the basics on Google, if there are any "gotchas" involved that would be useful!
Nate Lawson explains here and here why you can't securely use the public key as a closely-held secret decryption key (it's a subtle point, and a mistake plenty of others have made before you, so don't feel bad!).
Just use your public key to sign for authenticity, and a separate symmetric key for the secrecy.
I've read enough on interesting attacks against public key systems, and RSA in particular, that I agree absolutely with this conclusion:
Public key cryptosystems and RSA in
particular are extremely fragile. Do
not use them differently than they
were designed.
(That means: Encrypt with the public key, sign with the private key, and anything else is playing with fire.)
Addendum:
If you're interesting in reducing the size of the resulting cookies, you should consider using ECDSA rather than RSA to produce the signatures - ECDSA signatures are considerably smaller than RSA signatures of an equivalent security factor.
In cryptography you are what you know. In your scenario, you have a central authority which is able to issue your cookies, and you want no other entity to be able to do the same. So the central authority must "know" some private data. Also, you want the "trusted web servers" to be able to access the contents of the cookies, and you do not want just anybody do read the cookies. Thus, the "trusted web servers" must also have their own private data.
The normal way would be that the authority applies a digital signature on the cookies, and that the cookies are encrypted with a key known to the trusted web servers. What your are thinking about looks like this:
There is a RSA modulus n and the two usual RSA exponents d and e (such that ed = 1 modulo p-1 and q-1 where n=pq). The central authority knows d, the trusted web servers know e, the modulus n is public.
The cookie is processed by the central authority by padding it into an integer c modulo n, and computing s = c^d mod n.
The trusted web servers access the cookie data by computing c = s^e mod n.
Although such a scheme may work, I see the following problems in it:
For basic security, e must be large. In usual RSA descriptions, e is the public exponent and is small (like e = 3). A small exponent is no problem when it is public, but since you do not want cookie contents to be accessible by third parties, you must make e big enough to resist exhaustive search. At the same time, trusted web servers must not know p and q, only n. This means that trusted web servers will need to compute things with a big modulus and a big exponent, and without knowing the modulus factors. This seems a minor point but it disqualifies many RSA implementation libraries. You will be "on your own", with big integers (and all the implementation issues known as "side-channel leaks").
Resistance of RSA signatures, and resistance of RSA encryption, have been well studied, but not together. It so happens that the padding is essential, and you do not use the same padding scheme for encryption and for signatures. Here, you want a padding scheme which will be good for both signature and encryption. Cryptographers usually consider that good security is achieved when hundreds of trained cryptographers have looked at the scheme for a few years, and found no blatant weakness (or fixed whatever weaknesses were found). Home-cooked schemes almost always fail to achieve security.
If many people know a secret, then it is not a secret anymore. Here, if all web servers know e, then you cannot revoke a trusted web server privileges without choosing a new e and communicating the new value to all remaining trusted web servers. You would have that problem with a shared symmetric key too.
The problem of ensuring confidentiality and verifiable integrity in the same type is currently being studied. You may look up signcryption. There is no established standard yet.
Basically I think you will be happier with a more classical design, with digital signatures used only for signing, and (symmetric or asymmetric) encryption for the confidentiality part. This will allow you to use existing libraries, with the least possible homemade code.
For the signature part, you may want to use DSA or ECDSA: they yield much shorter signatures (typically 320 bits for a DSA signature of security equivalent to a 1024-bit RSA signature). From the central authority point of view, ECDSA also allows better performance: on my PC, using a single core, OpenSSL crunches out more than 6500 ECDSA signatures per second (in the P-192 NIST curve) and "only" 1145 RSA signatures per second (with a 1024-bit key). The ECDSA signatures consist in two 192-bit integers, i.e. 384 bits to encode, while the RSA signatures are 1024-bit long. ECDSA in P-192 is considered at least as strong, and probably stronger, than RSA-1024.
You should use a digital sigantures scheme of some sort, or some other mechanism that is aimed to solve the integrity problem of your scenario.
The encryption itself isn't enough.
How would you know that the decrypted messege is what it should be?
Decrypting a cookie encrypted with the right key will surely provide a "valid" cookie, but what happens when you decrypt a cookie encrypted with the wrong key? or just some meaningless data? well, you might just get a cookie that looks valid! (the timestamps are in the range you consider valid, the username is legal, the random number is... uh... a number, etc.).
In most asymmetric encryption algorithms I know off, there is no built-in validation. That means that decrypting a message with the wrong key will not "fail" - it will only give you a wrong plaintext, which you must distinguish from a valid plaintext. This is where integrity comes to play, most commonly - using digital signatures.
BTW, RSA is long studied and has several "gotchas", so if you plan to implement it from scratch you better read ahead on how to avoid creating "relatively easy to break" keys.
Public keys are by definition, public. If you're encrypting with a private key and decrypting with a public key, that's not safe from prying eyes. All it says: "this data is coming from person X who holds private key X" and anyone can verify that, because the other half of the key is public.
What's to stop someone you don't trust putting public key X on a server you don't trust?
If you want a secure line of communication between two servers, you need to have all of those trusted servers have their own public/private key pairs, we'll say key pair Y for one such server.
Server X can then encrypt a message with private key X and public key Y. This says "server X sent a message that only Y could read, and Y could verify it was from X."
(And that message should contain a short-lived symmetric key, because public key crypto is very time-consuming.)
This is what SSL does. It uses public key crypto to set up a session key.
That being said, use a library. This stuff is easy to screw up.
The answer to your question "would the act of decrypting be evidence that it was generated with the private key", the answer is yes if the recipient can do simple validation of the data. Say you have "User name : John, timestamp : <number>, expiry : dd/mm/yyyy". Now if a wrong public key is used to decrypt, the probability that you will get "User name : <some letters>, timestamp : <only numbers>, expiry : ??/??/????" is zero. You can validate using a regular expression (regex) like "User name : [a-zA-Z]+, timestamp : [0-9]+, expiry : .... " and drop it validation fails. You can even check if the day is between 1 and 31, month is between 1 and 12 but you won't get to use it as regex will typically fail at "User name : " if wrong public key is used. If validation succeeds you still have to check the timestamp and ensure that you don't have a replay attack.
However, consider the following:
RSA public key crypto is not designed for bulk encryption of structured data as it can be exploited by attacker. public key crypto is typically used in 2 ways: 1) for securely transporting the symmetric key (which by definition has no structure) which will be used in bulk encryption; this is done by encrypting the symmetric key using the public key and 2) digitally signing a document by encrypting not the document but the hash of the document (again something which has no structure) using the private key. In your case you are encrypting the cookie which has a definite structure.
You are depending on the public key not getting into the hands of the wrong person or entity.
public key encryption is about 1000 times slower that symmetric key encryption. This may not be a factor in you case.
If you still want to use this approach, and are able to distribute the public key only to the "trusted partners", you should generate a random session key (i.e. symmetric key), encrypt it using the private key and send to all recipients who have the public key. You then encrypt the cookie using the session key. You can change the session key periodically. More infrequently you can change the public key also: you can generate a new public/private key pair and encrypt public key with the session key and send it to all recipients.
I presume you trust the 'trusted partners' to decrypt and verify the cookie, but don't want them to be able to generate their own cookies? If that's not a problem, you can use a much simpler system: Distribute a secret key to all parties, and use that to both encrypt the cookie and generate an HMAC for it. No need for public key crypto, no need for multiple keys.
As an alternative to your key distribution approach, which may or may not be suitable in your application, consider using Kerberos, which uses symmetric key encryption, a single highly protected bastion server that controls all the keying material, and a clever set of protocols (See the Needham-Schroder protocol)