doulv1760 2017-06-27 16:14
浏览 69
已采纳

CRAM-MD5验证期间的不同哈希

As an exercise, I'm trying to implement a mock SMTP server with CRAM-MD5 authentication in Go (without following RFC 2195, since it looks like it doesn't matter to the client what format the pre-hashed challenge is in; I also assume there is only one user "bob" with password "pass"). But I can't seem to get it right as the hash in response is always different from what I have on the server. I send the email using Go as such (running it as a separate package):

{...}
smtp.SendMail("localhost:25", smtp.CRAMMD5Auth("bob", "pass"),
   "bob@localhost", []string{"alice@localhost"}, []byte("Hey Alice!
"))
{...}

Here's what I do when I get the authentication acknowledgement from the client:

{...}
case strings.Contains(ms, "AUTH CRAM-MD5"):
    rndbts = make([]byte, 16) // Declared at package level
    b64b := make([]byte, base64.StdEncoding.EncodedLen(16))
    rand.Read(rndbts)
    base64.StdEncoding.Encode(b64b, rndbts)
    _, err = conn.Write([]byte(fmt.Sprintf("334 %x
", b64b)))
{...}

And this is what I do with the client's response:

{...}
 {
    ms = strings.TrimRight(ms, "
") // The response to the challenge
    ds, _ := base64.StdEncoding.DecodeString(ms)
    s := strings.Split(string(ds), " ")
    login := s[0] // I can get the login from the response.
    h := hmac.New(md5.New, []byte("pass"))
    h.Write(rndbts)
    c := make([]byte, 0, ourHash.Size()) // From smtp/auth.go, not sure why we need this.
    validPass := hmac.Equal(h.Sum(c), []byte(s[1]))
    {...}   
}
{...}

And the validPass is never true. I omitted error handling from the excerpts for brevity, but they're there in the actual code (though they're always nil). Why are the hashes different? I have looked at the source code for net/smtp, and it seems to me that I'm going in the right direction, but not quite.

  • 写回答

1条回答 默认 最新

  • doumi4974 2017-06-28 00:12
    关注

    I hope this helps! Runnable version is at https://play.golang.org/p/-8shx_IcLV. Also note that you'll need to fix your %x (should be %s) so you're sending the right challenge down to the client. Right now I think you're trying to hex-encode your base64 string.

    Once you've fixed that, I believe this code should help you to construct the right response string on the server and compare it to what the client sent.

    // Example values taken from http://susam.in/blog/auth-cram-md5/
    
    challenge := []byte("<17893.1320679123@tesseract.susam.in>")
    username := []byte("alice")
    password := []byte("wonderland")
    clientResponse := []byte("YWxpY2UgNjRiMmE0M2MxZjZlZDY4MDZhOTgwOTE0ZTIzZTc1ZjA=")
    
    // hash the challenge with the user's password
    h := hmac.New(md5.New, password)
    h.Write(challenge)
    hash := h.Sum(nil)
    
    // encode the result in lowercase hexadecimal
    hexEncoded := hex.EncodeToString(hash)
    
    // prepend the username and a space
    toEncode := []byte(string(username) + " " + hexEncoded)
    
    // base64-encode the whole thing
    b64Result := make([]byte, base64.StdEncoding.EncodedLen(len(toEncode)))
    base64.StdEncoding.Encode(b64Result, toEncode)
    
    // check that this is equal to what the client sent
    if hmac.Equal(b64Result, clientResponse) {
        fmt.Println("Matches!")
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 运筹学排序问题的应用
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料
  • ¥15 使用R语言marginaleffects包进行边际效应图绘制
  • ¥20 usb设备兼容性问题
  • ¥15 错误(10048): “调用exui内部功能”库命令的参数“参数4”不能接受空数据。怎么解决啊
  • ¥15 安装svn网络有问题怎么办