Using Astors post as an example: Astor wrote this message. first their GPG program notes that the hashing algorithm used was SHA512. Then GPG takes the SHA512 value of the message: 41aef97732043975c8ba34dedb2aeb7c4419677b2fcde5d4c869184837d37a542870a136c812d5ae172b6d4b6ce7e19a07c534fef0fe0cf93ec315644347440 next it unbase64s the signature, and then it decrypts the signature with Astor's public key, revealing the hash value (again I am skipping the step that removes padding). Next GPG compares the hash value of the message to the value it obtained after unbase64ing, decrypting and removing padding from the signature. If they both match, then it verifies that the message was signed by Astor, otherwise it says the signature is not valid. 41aef97732043975c8ba34dedb2aeb7c4419677b2fcde5d4c869184837d37a542870a136c812d5ae172b6d4b6ce7e19a07c534fef0fe0cf93ec315644347440 == 41aef97732043975c8ba34dedb2aeb7c4419677b2fcde5d4c869184837d37a542870a136c812d5ae172b6d4b6ce7e19a07c534fef0fe0cf93ec315644347440 When it compares the two strings, it must do so in constant time to avoid the possibility of a timing attack. Normally when two strings are compared, the comparing algorithm breaks on the first mismatch. In this case we need to compare every single character, even if there are mismatches, so that successful or unsuccessful verification takes exactly the same amount of time. This is just a rough sketch of what GPG is doing when signing and verifying signatures with RSA, I definitely missed at least one step.