What's wrong with my security model - or how can it be attacked? I'm working on a little personal project where security is very important, and I've thought for a while about the best way to do this. Now I am looking for a little outside help on good practices. The goal is to store personal text data on a server (like wifi passwords, etc) and be obtained through a password. I wanted to make user accounts for a few friends so that we each could securely store text snippets and retrieve them without the others knowing them. Here's my data structures:

// Account
- Username
- Password
- Salt

// StoredData
- Title
- Info
- User


Okay, now the fun part. Here's how I'm obfuscating the data. When a friend creates an account, their username is salted with a salt in the server config files (this is Rails btw, so ENV['SALT']) and then SHA256'd. The password is generated via BCrypt. The only thing I'm not sure about are how many rounds to do for BCrypt so the server stays snappy; right now it's at default for ruby's bcrypt library. A random salt is also saved in the Account for the next step.

Username = SHA256(username + SERVER_SALT)
Password = BCrypt(password)
Salt = BCrypt.generateSalt


When a friend saves their data, it is encrypted using AES-256. So for this, an AES Key is generated using a combination of their plaintext username and password, as well as the salt generated in Account creation. That key is never stored on the server, but created on device at runtime.

         PBKDF2_HMAC_SHA1(secret, salt, rounds)
AESKey = PBKDF2_HMAC_SHA1((usernamepassword), Account.Salt, 20000)
Title = AES-256(AESKey, title)
Info = AES-256(AESKey, info)


Last but not least, every time you login, you are given a SessionKey that enables you to perform any function like editing or creating new data. This SessionKey rolls after every action. So, on login you get S1, then you make a new piece of data and S1 is deleted and S2 is given to you. So on and so forth. Each SessionKey has a one hour time limit as well. Here's my data structure for that:

// SessionKey
- Key (32-bit GUID)
- HashedUser
- ExpirationDate


Also, the whole thing is sent back and forth over SSL, though after the recent revelations I'm not too sure how secure that is anymore. My question to the community is - what am I doing wrong? No crypto implementation is being rolled by me, I'm just using multiple stock implementations. BCrypt is 10 rounds and PBKDF2 is 20,000 right now. Are those high enough for contemporary cryptography and the computer systems I know some people have? Are there any gaping holes? Is the whole thing wishful thinking?
Usernames

A hashed username is fine; a nice idea for the security paranoid actually. If all username records use the same salt, then a rainbow attack is theoretically possible - as is knowing that a user has X pieces of secured information (plus timestamps etc). But you need a single salt per table if the username is the tuple selection mechanism.

Secret Snippet (Title/Info/Visible Timestamps)

Depending on other features this service is providing, the password needn't be stored server-side to secure the secret snippets; thus avoiding the time cost of bcrypt. If user enters the wrong password your service can happily decrypt and return semantic garbage. If the user enters an unmatched username the server can happily invent a random editable list of random data; breaking any clue about viable usernames. Context-specific flags or checksum verification could be used by the client agent to discard deciphered garbage.

Storing a password on a server is usually used for authentication instead of  confidentiality. Whether a computer should do something for someone - instead whether the data returned is fit-for-purpose. The users can simply be told to pick an unguessable username if they don't want their data erased or modified; in a manner similar to disposable email inboxes. If the username is guessed, the content is still unintelligable.

Session Key

Seems legit. If session doesn't include the decryption password or aggregate AES key and user wants to see the plaintext content, the user's client-side will need to cache the password or plaintext; or the persistent session will still bug the user for a password on each page refresh.

Other Thoughts

Alternately, if the service simply stores secure information; then an ad-hoc public key approach can be used with decryption occurring on the client-side. And yes, to those naysayers, you can have unverified use of public keys; if a service is indifferent to whether the human using the username has changed or simply their password. A SSL framework provides the protection against man-in-middle attacks. If it doesn't - you have to reinvent a much larger wheel.