First to clarify, the HMAC code does not generate a signature. It is a type of Message Authentication Code (MAC).
The latter link explains the difference between a signature and a MAC this way:
MACs differ from digital signatures as MAC values are both generated
and verified using the same secret key. This implies that the sender
and receiver of a message must agree on the same key before initiating
communications, as is the case with symmetric encryption. For the same
reason, MACs do not provide the property of non-repudiation offered by
signatures specifically in the case of a network-wide shared secret
key: any user who can verify a MAC is also capable of generating MACs
for other messages. In contrast, a digital signature is generated
using the private key of a key pair, which is asymmetric encryption.
Since this private key is only accessible to its holder, a digital
signature proves that a document was signed by none other than that
holder. Thus, digital signatures do offer non-repudiation. However,
non-repudiation can be provided by systems that securely bind key
usage information to the MAC key; the same key is in possession of two
people, but one has a copy of the key that can be used for MAC
generation while the other has a copy of the key in a hardware
security module that only permits MAC verification. This is commonly
done in the finance industry.
So in order to verify an HMAC, you need to share the key that was used to generate it. You would send the message, the HMAC, and the receiver would have the same key you used to generate the HMAC. They could then use the same algorithm to generate an HMAC from your message, and it should match the HMAC you sent. Public/private keys (assymetric) are not used for this. You need to generate a symmetric key (like AES) and securely share that with the people that will be generating/verifying the HMAC.
This limits the HMAC to having integrity
and authenticity
properties only, and not non-repudiation
.
The quote above mentioned that hardware security modules could be used to enforce the key use, and then you could get non-repudiation as long as only one person could use the key for generating the HMAC.
Alternatively, you could use a hybrid approach. Use a shared symmetric key to generate the HMAC. The HMAC in the end is a hash. You could then sign this hash with your private key (different than the key used in the HMAC). A third party with the symmetric key and your public key could verify you signed the HMAC, and could generate their own HMAC with the message and the shared key to make sure it matched. This would also give you non-repudiation.
If you want to go this route, use the Java Signature class. The HMAC algorithm is SHA-1, and assuming your keypair is RSA, you could use the NONEwithRSA
Signature algorithm since the input is already a SHA-1 hash. Or you could hash it again with the SHA1withRSA
algorithm. As long as you generate the signature and verify with the same algorithm, it should be OK.
byte[] data = hmac.getBytes("UTF-8");
Signature mySig = Signature.getInstance("NONEwithRSA");
mySig.initSign(myPrivateKey);
mySig.update(data);
byte[] sigBytes = mySig.sign();
// And to verify.
Signature mySig2 = Signature.getInstance("NONEwithRSA");
mySig2.initVerify(myPublicKey);
boolean isSigValid = mySig2.verify(sigBytes);