Skip to content

Commit

Permalink
export password hashing funcs and move to wire pkg
Browse files Browse the repository at this point in the history
  • Loading branch information
mk6i committed May 20, 2024
1 parent 075be5e commit e7eb9ce
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 33 deletions.
37 changes: 4 additions & 33 deletions state/user_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@ package state

import (
"bytes"
"crypto/md5"
"database/sql"
"embed"
"errors"
"fmt"
"io"
"io/fs"
"net/http"
"time"
Expand Down Expand Up @@ -65,46 +63,19 @@ func (u *User) ValidateHash(md5Hash []byte) bool {
// hash of the user's actual password. A roasted password is a XOR-obfuscated
// form of the real password, intended to add a simple layer of security.
func (u *User) ValidateRoastedPass(roastedPass []byte) bool {
var roastTable = [16]byte{
0xF3, 0x26, 0x81, 0xC4, 0x39, 0x86, 0xDB, 0x92,
0x71, 0xA3, 0xB9, 0xE6, 0x53, 0x7A, 0x95, 0x7C,
}
clearPass := make([]byte, len(roastedPass))
for i := range roastedPass {
clearPass[i] = roastedPass[i] ^ roastTable[i%len(roastTable)]
}
md5Hash := weakMD5PasswordHash(string(clearPass), u.AuthKey) // todo remove string conversion
clearPass := wire.RoastPassword(roastedPass)
md5Hash := wire.WeakMD5PasswordHash(string(clearPass), u.AuthKey) // todo remove string conversion
return bytes.Equal(u.WeakMD5Pass, md5Hash)
}

// HashPassword computes MD5 hashes of the user's password. It computes both
// weak and strong variants and stores them in the struct.
func (u *User) HashPassword(passwd string) error {
u.WeakMD5Pass = weakMD5PasswordHash(passwd, u.AuthKey)
u.StrongMD5Pass = strongMD5PasswordHash(passwd, u.AuthKey)
u.WeakMD5Pass = wire.WeakMD5PasswordHash(passwd, u.AuthKey)
u.StrongMD5Pass = wire.StrongMD5PasswordHash(passwd, u.AuthKey)
return nil
}

//goland:noinspection GoUnhandledErrorResult
func weakMD5PasswordHash(pass, authKey string) []byte {
hash := md5.New()
io.WriteString(hash, authKey)
io.WriteString(hash, pass)
io.WriteString(hash, "AOL Instant Messenger (SM)")
return hash.Sum(nil)
}

//goland:noinspection GoUnhandledErrorResult
func strongMD5PasswordHash(pass, authKey string) []byte {
top := md5.New()
io.WriteString(top, pass)
bottom := md5.New()
io.WriteString(bottom, authKey)
bottom.Write(top.Sum(nil))
io.WriteString(bottom, "AOL Instant Messenger (SM)")
return bottom.Sum(nil)
}

// SQLiteUserStore stores user feedbag (buddy list), profile, and
// authentication credentials information in a SQLite database.
type SQLiteUserStore struct {
Expand Down
45 changes: 45 additions & 0 deletions wire/user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package wire

import (
"crypto/md5"
"io"
)

// WeakMD5PasswordHash hashes password and authKey for AIM v3.5-v4.7.
//
//goland:noinspection ALL
func WeakMD5PasswordHash(pass, authKey string) []byte {
hash := md5.New()
io.WriteString(hash, authKey)
io.WriteString(hash, pass)
io.WriteString(hash, "AOL Instant Messenger (SM)")
return hash.Sum(nil)
}

// StrongMD5PasswordHash hashes password and authKey for AIM v4.8+.
//
//goland:noinspection ALL
func StrongMD5PasswordHash(pass, authKey string) []byte {
top := md5.New()
io.WriteString(top, pass)
bottom := md5.New()
io.WriteString(bottom, authKey)
bottom.Write(top.Sum(nil))
io.WriteString(bottom, "AOL Instant Messenger (SM)")
return bottom.Sum(nil)
}

// RoastPassword toggles password obfuscation using a roasting algorithm for
// AIM v1.0-v3.0 auth. The first call obfuscates the password, and the second
// call de-obfuscates the password, and so on.
func RoastPassword(roastedPass []byte) []byte {
var roastTable = [16]byte{
0xF3, 0x26, 0x81, 0xC4, 0x39, 0x86, 0xDB, 0x92,
0x71, 0xA3, 0xB9, 0xE6, 0x53, 0x7A, 0x95, 0x7C,
}
clearPass := make([]byte, len(roastedPass))
for i := range roastedPass {
clearPass[i] = roastedPass[i] ^ roastTable[i%len(roastTable)]
}
return clearPass
}

0 comments on commit e7eb9ce

Please sign in to comment.