Add a "signature_algorithm" key to the response. Also, allow the request to specify a list of acceptable algorithms, like {"id": "1234", "signatures_accepted": "ecdsa: SECP256r1, SECP521r1; pkcs 1", "firstbits": "1payBTC"}
good idea
As for actually calculating it, there are two ways to go. In a binary protocol/format or when the length of the signature is known in advance, it is common to construct the response using zeros to fill in the signature field, then calculate the signature based on that, then overwrite the zeros with the actual signature. In a text stream like this, I would build the response without the signature key and value, then construct a new response that includes them. Or just insert them, modern languages have no problem chopping and splicing strings, and C programmers already have lots of practice doing it the hard way.
Yes, I was thinking about this, too. Unfortunately it's getting slightly complicated, because there are also some other fields which can be changed without corrupting the signature, like message "id". It's because ID must be unique in particular session, but this signed response can be created as a response to some proxy call to backend (in the firstbits example, signature is created directly by firstbits service, but signature must be valid also as a response from overlay server to client.
Another issue is that fields in json-rpc don't have strict order, so two identical and valid json-rpc may have different signature (well,
2112 must be laughing now :-) ). This is problematic for validating messages, because you need to extract fields which are not part of signed message, but not affect message payload.
This leads me to conclusion that trying to sign/verify message itself can be very fragile. I also don't want to go against json-rpc specification and force such things like order of fields. Currently I don't know how to decide this issue, is there any best practice to doing this?
How other text-based protocols solve such problem?For the usual case, you don't care that multiple messages might be equally valid. The signature is for "this message", not for "any message bearing the same content as this message".
If you are worried that a proxy might replace the message with a message that is different but equivalent, then you need to have a canonical form, and you should only emit the canonical form. When the client receives a message, it must convert it into canonical form before checking the signature.
As for the ID, don't leave it out of the signature unless you enjoy replay attacks. Just force the client to make it globally unique. There are already well established techniques for doing this.