In gpg, "decrypting" a signed message without the public key - cryptography

I know how to use gpg to sign messages or to verify signed messages from others. But I recently noticed that you can "decrypt" a signed message without access to their public key [although you can't verify the signature].
For example, here is a small signed message.
-----BEGIN PGP MESSAGE-----
Version: GnuPG v1
owEBrAJT/ZANAwACAULhWJW/fwKRAax8YgdtZXNzYWdlWFVuX0hlbGxvIFN0YWNr
T3ZlcmZsb3cuCgpZb3UgY2FuIHJlYWQgdGhpcyBtZXNzYWdlLCBldmVuIHRob3Vn
aCB5b3UgZG9uJ3QgaGF2ZSBteSBwdWJsaWMga2V5LiBIb3cgZG9lcyB0aGF0IHdv
cms/CokCHAQAAQIABgUCWFVuXwAKCRBC4ViVv38CkXl6D/oCvgOGKFx7c0IDAI9q
2wsj35bapllGlxCRK5/Z8sYqM2RpcV+//wArozMTndFj60ZevMIrPYyWEUyKYS6l
kgq6euD2hbcoy/bcP/3z51K3zCtXby4/CKgx6E1ecC94iO89hVoYQkLWtgRWiL8Z
wfGWgr8X0MaGzsU5q/SchJfZj5ox32JN0S8Iqfqk+xJe2CdQ4KRpbS3M5I3u8/yX
E5ETUeO3aFPwmrBysJysGozWatoiDlMvuiLfnW+Qs4DkEpSRxOw2Sx+ufE2wmWlJ
+5Q4OJiEL6TmJ+Di201CHDGFPWVkrGDioMt6x07vyyiW6X2k4vmIjbFL9vtypUfF
4VzzCWRX9BTCVZZo4ULUmkNznF1IkYJ03TlEFqfTrQ6Jq3SeqlzjGY3I4LJ1a9cL
eobIECLFLqTmOmXM5oC/38V2kNA+/NoSNkw+H78sIlfQ8919JktVG+oa6mEP2OQ8
7k3W7nSpcKugGYDXBB5HQa8lPq1lgI9H+j05pCAhoNnff6Ynl223ycva0xq5wOs/
mjViRWDn+RUebp3KcN/PW7Bkf9RsKt/sPJl2IPdDwdaBibUkhIEKfWVpaOd9rlK6
06/bD+momYpXSlmE/eYh+pf8aIj2R+7Ciz8fAqrTU2hPSWoi2Ne/ISwLBJS4wmRZ
OnHYDOXulQBor1K+VgKyYclC2Q==
=5/kF
-----END PGP MESSAGE-----
Unlike many signed messages, this message isn't plain-signed. I had thought that without access to the public key for this message, it wouldn't be possible to read it, let alone to verify it.
But if one uses gpg --decrypt on this message, it is able to produce the plaintext version. Alternately, if you use a service like Keybase for gpg, then Keybase is also able to produce the plaintext. What exactly is going on?
A first thought would be that the public key is somehow included in the message, but it appears that this is not true. The fingerprint of the public key is included, though that shouldn't be enough to decrypt the message, right?

GPG with --sign --armor produces base64-encoded (more precisely Radix-64-encoded) output where the message body is still readable by simply base64-decoding the output.
So I guess another way to put it is that the message is encoded but not encrypted.
To see, run the PGP message in the question through any base64 decoder (e.g., some online one).
Because the message isn’t encrypted but instead only signed, then no key is needed to decrypt it. It’s just a signature and some text wrapped up together. So GPG unwraps it without needing a key.
The word “wrapped” here is just shorthand. Here’s a more detailed explanation:
every PGP message contains a set of what the OpenPGP spec calls “packets”
for --sign output, GPG encodes a message containing (1) a Literal Data Packet that holds the message body and (2) a Signature Packet
when --decrypting --sign output, GPG just decodes it; it decodes the literal-data-packet part to get the (unencrypted) message body and the signature-packet part to get the signature
So recipients only need the key if they want to check the message text against the signature. They don’t need the key to just read the message. They only need GPG or some other implementation of the OpenPGP Message Format standard that understands how to decode the message format.
As far as encryption, there’s no difference between that --signed message and one signed with --clearsign. Neither is encrypted. The only difference otherwise is that for a message signed with --sign, a recipient needs to use GPG to unwrap the text from the signature, while for a message signed with --clearsign, the recipient can see the message text without needing GPG.

Further to the accepted answer, even if the message was encrypted - it would be done so with your public key, and since you have the private key, you can decrypt it. The only purpose that the signature and validation serves, is to 'prove' who sent you the message. If you don't care who it came from, you can still decrypt any PGP message sent to you by ignoring the signature - you just can't be sure it came from who you think it came from.

Related

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.

Send RSA public key over socket them import it for encryption [VB .NET]

I'm writing that generates public and private key pair, then send the public key over the socket to another programs to be used to encrypt string data.
I'm using RSA in VB.NET and I was able to generate the required keys:
My public key v+u4Lt4nyLXincU+wbReOTU3nwiTZ7MlFkA7cytLOjuviHrAdnaVAV8+WoFhy9nADGtk1K0OLAE1ZwGzt/kgUw==
My question is: is the public key enough for encryption by other users? and if so, how can I import it to RSA parameters to encrypt data?
Edit:
I used the following code in an attempt to import the public key but it failed:
Dim Parameters As New RSAParameters
Parameters.Modulus = encoder.GetBytes(publicKey)
RSA.ImportParameters(Parameters)
My question is: is the public key enough for encryption by other
users?
The answer is as so often: It depends.
The way you describe your proposed protocol this would be widely open to man-in-the-middle-attacks. Eve could just intercept the message on the wire and replace the key by her own.
From a theoretical point of view, it is sufficient to encrypt data. However, to be useful in real world scenarios, you have to use symmetric encryption as well.
So here is my advice:
Don't do your own protocols if you have to ask such questions. Never. Not once. Use Well known, established technology like TLS!
I had a similar project in VB.net, you will not be able to send messages of a large length because if you are using 2048bit RSA, the maximum size of data you would be able to send would be 245 bytes. https://security.stackexchange.com/questions/33434/rsa-maximum-bytes-to-encrypt-comparison-to-aes-in-terms-of-security
I used the RSA public key so each client would use AES encryption and pass their own keys which are encrypted with RSA, the server would then decrypt the key and use that to resolve data. This uses both asymmetric(RSA) and symmetric encryption(AES). Here is a link with a useful video that explains this when I was doing this project. https://www.youtube.com/watch?v=6H_9l9N3IXU&t=271s
The way I imported the keys was using the .toXMLString and .fromXMLString in the RSA CryptoServiceProvider. Here is a great link explaining it, probably doing a better job that I could. https://msdn.microsoft.com/en-us/library/system.security.cryptography.rsa.toxmlstring(v=vs.110).aspx
I found this page that was very useful for me here
Also I found that I was making the mistake of converting the encrypted byte array to string after encryption then back to byte array just before decryption. The last byte array didn't have the same size as the original.

Confused how to use AES and HMAC

I'm a little bit confused how to use AES and HMAC (based on SHA-256) in a proper way when transmitting the encrypted message from server to client or vice versa
Correct me please if the following method is wrong:
Take the secure key from the key file (for example we suggest to use the AES-256 and we already have a valid 256 bit length key)
Generate random IV for AES-256 to be sure that the same plain text will have different encryption output.
Calculate HMAC-SHA-256 using the plain text and secure key. (The first question: should I use IV for HMAC calculation? For example append to secure key?)
Encrypt the plain text using AES-256.
Compose message for client as following: HMAC + IV+ ENCRYPTED_MESSAGE
The biggest question is: is it possible somehow not to send IV to client but instead generate it the same way and still be crypto safe? Or is it ok to send the IV too?
I've end up with random IV generation, because it is needed that the same plain text will end up in different encryption results.
Don't send hmac(message),aes(message). If you send the same message twice, anyone can tell. Moreover, you need to mac the cipher-text to prevent attacks such as the padding oracle attack.
IV: In general, the easy way to deal with the iv is to prepend it, since it's fixed length, to the cipher text.You can then just read off those bytes before decrypting. IV's can be public, but they must be random.
HMAC: Easiest way, if your library supports it, is to use AES in GCM mode (or, less preferably EAX). This is not actually an HMAC, but it provides authenticated encryption which is just as good.If these are not supported :
You do need to compute the hmac over both the iv and the cipher text. if || is concatenation ( which you could do with say array copy if dealing with byte arrays) then you want
CipherText = iv|| aes(key1,iv,message)
tag = hmac(key2,ciphertext)
And then send (tag,CipherText). On the other end, you run the same hmac call to regenerate the tag and the compare the received tag with the computed one. Compare the sha1 or sha256 hashes of the tags instead of directly so you don't leak where the comparison fails.
You should use a different key for the hmac. In practice tacking the sha1 sum of your encryption key is good enough.

Niche, possible Naive digital message signing

My goal is a lightweight kind of message signing, comparable to PGP, except there is only a need for one private-key, no public-key associate. The goal is merely to prevent tampering of a string between two trusted entities. It starts from a trusted source, goes over the internet, then arrives at another trusted destination.
I would like to know if my naive approach is secure. In that the signing algorithm would not be practically brute forced.
1) Both source and destination have a "private key" which is just a very random number generated by uuidgen.
2) Source has a string it intends to send to destination.
3) Source concatenates the payload string with the private key, and then sha1's the result, to produce a signature.
4) The resulting plain-text value + signature are sent to destination in a pair. "hello//SIG:12345ABCDEFG"
5) Desination receives the signed-variable, generates a signature with its known private-key, and compares agains the signature paired with the received data. If they match, it is accepted.
A variation of this will incorporate a unix timestamp rounded to the hour, making the signature expire.
My concern is if it would be feasible to bruteforce the private key given a selective set of data payloads and analyzing the resulting signatures with this approach.
Thanks
It seems like what you want to achieve is very similar to an HMAC (article on Wikipedia).
For an HMAC, you perform some additional steps to combine message and secret key into a hash. This makes the resulting hash harder to attack than one which results from simply concatenating original message and secret key and hashing that.
If you want to use cryptographic standards as much as possible (which - in my opinion - is almost always a good thing), I would look into doing it the way the HMAC definition prescribes. To make the signature expire, I would simply attach the expiration date to the message and then build the HMAC of that combined string.

Is this RSA-based signature (with recovery) scheme cryptographically sound?

I am implementing a simple license-file system, and would like to know if there are any mistakes I'm making with my current line of implementation.
The message data is smaller than the key. I'm using RSA, with a keysize of 3072bits.
The issuer of the licenses generates the message to be signed, and signs it, using a straightforwards RSA-based approach, and then applies a similar approach to encrypt the message. The encrypted message and the signature are stored together as the License file.
Sha512 the message.
Sign the hash with the private key.
Sign the message with the private key.
Concatenate and transmit.
On receipt, the verification process is:
Decrypt the message with the public key
Hash the message
Decrypt the hash from the file with the public key, and compare with the local hash.
The implementation is working correctly so far, and appears to be valid.
I'm currently zero-padding the message to match the keysize, which is probably
a bad move (I presume I should be using a PKCS padding algorithm, like 1 or 1.5?)
Does this strategy seem valid?
Are there any obvious flaws, or perspectives I'm overlooking?
The major flaw I noticed: you must verify the padding is still there when you decrypt.
(If you know the message length in advance then you might be able to get away with using your own padding scheme, but it would probably still be a good idea to use an existing one as you mentioned).
I am not sure why you're bothering to encrypt the message itself - as you've noted it can be decrypted by anyone with the public key anyway so it is not adding anything other than obfuscation. You might as well just send the message and the encrypted-padded-hash.
I would recommend using a high level library that provides a "sign message" function, like cryptlib or KeyCzar(if you can). These benefit from a lot more eyeballs than your code is likely to see, and take care of all the niggly padding issues and similar.