July 12th, 2012, 09:16 PM
RSA Verification in Browser for Chiptune Website, padding needed?
Hi! I'm the developer of a website for creating chiptune music called beepbox. I'm not allowed to post URLs yet since I'm a new user, but you can google it if you're interested.
I'm investigating ways to provide some notion of authenticity when people publish songs through my interface. I've been doing a bunch of research on cryptography to come up with a plan, but I'm not a professional security expert so I definitely need a few more eyeballs to take a look at it before I commit to it. I'd appreciate any advice you guys have, including connections with other people who know what they're talking about.
There are two problems I'm trying to solve:
1. You should not be able to take a song you wrote and claim someone else wrote it. I'm actually not too worried about this kind of abuse (who would even do that and what would it accomplish?) so my solution doesn't need to be 100% secure here, just difficult. My current plan is that authors provide a "password" that gets hashed and then visualized as an avatar, much like Gravatar defaults. So if two songs have different avatars, then either they were submitted by different people or one person figured out the other's password.
2. You should not be able to take someone else's song and claim that you wrote it first. (You are welcome to publish derived songs, since imitation is an important part of learning, not to mention flattery.) I imagine this sort of abuse would be more likely and more damaging. So in my plan, when you publish a song, the date is provided by a server acting as an authority, so nobody can lie about when they published a song. It sounds like we're gonna need a digital signature with the private key on the server, asserting that this song was published by someone claiming to be this author on this date.
My plan is made trickier by the self-imposed, unorthodox constraint that I don't store any user-data on my server. There are a bunch of reasons for this constraint, but the short version is that I want to see how much I can rely on URL fragments to share data. At the moment, all song data is represented in the URL after the # mark, while the server has entirely static content, and I'd like to keep it that way if possible. This means that the only secret I have to work with is a static private key on the server. Everything else is public, including the entirety of all previously signed messages and their signatures.
On my server, I'm using PyCrypto, which supports vanilla RSA signing as well as some more advanced schemes. On the browser, however, the best option I've found so far is AS3Crypto, which seems to support vanilla RSA verification and also claims to support padding but isn't very clear on what kind of padding it supports and hasn't been maintained. Any other suggestions?
It's not hard for me to add my own padding to a message on the server before signing it, in fact I'm already adding a date to the message and could easily add some random gibberish. Assuming I can get vanilla RSA to work, what do I need to know about padding to make sure I'm preventing forgery?
Sorry about the wall of text, and thanks in advance for any help!
July 13th, 2012, 04:50 PM
A quick update: I've been playing with PyCrypto and As3Crypto and I've confirmed that I can perform vanilla RSA signing in the former and verify it in the latter. Currently investigating padding options in As3Crypto but so far it looks grim.
July 13th, 2012, 09:14 PM
Alright, turns out not even PyCrypto supports RSA signature padding, at least not the version I'm using. (PyCrypto 2.3, integrated with Google App Engine.)
So it sounds like it's up to me to do the padding myself. I understand that nobody recommends DIY cryptography, which is why I'm here asking questions to make sure I get it right.
So I see that there's basically two kinds of RSA signature padding in use: PSS and PKCS-v1.5. PSS is theoretically stronger, but given our present understanding it sounds like both are equally hard to crack. PKCS-v1.5 is probably good enough for my purposes, and fortunately it looks like it's dead simple to implement.
Technically you're supposed to put the hash inside some "DER" encoding before padding, but I get the impression that this is purely for documentation rather than for any cryptography reasons, right? Since I'm doing the both the signing and verification parts internally, I figure I'll skip that step and just add padding to the hash directly.
In that case all I have to do is add these bytes to the front of the hash before signing it with RSA until it's 256 bytes long:
00 || 01 || ff || ff || ff || ... || ff || 00 || hash
I wonder if it's a terrible idea to use random bytes instead of all those ff bytes... Yeah, better not chance it I guess.
So how about it? Are you guys laughing at my naiveté yet? :P