DDP로 인증을 하려면 네트웍상에 평문으로 보내지 않기 위해
SRP(Secure Remote Password) 라는 프로토콜로 변환한다.
https://github.com/meteor/meteor/tree/devel/packages/srp
package.js 를 보면 biginteger 와 sha256 을 사용한다.
구현해야할 부분은 https://github.com/meteor/meteor/blob/devel/packages/accounts-password/password_client.js#L10
이 곳 참조.
password 를 가지고 다음과 같이.
s = new srp.Client password
request = s.startExchange()
if typeof selector == 'string'
selector =
if ~selector.indexof("@")
then username: selector
else email: selector
request.user = selector
beginPasswordExchange 를 시작하는 부분의 인자는 request 자체를 사용.
request 내용은 A를 키로 하는 SRP 암호문과 user를 키로하는 사용자명이 되겠다.
method 쏴준다. A에 srp로 암호화한 문자를 사용.
{ msg: 'method',
method: 'beginPasswordExchange',
params:
[ { A: '439284960ce6bc7c163262b5629a467cd06bb982432615ec526a1ed204d2f76a1a254faaab6c5c9309e120d708e3e46fe58d8c5017aedb85efb9670cfcbf8a8b2dd996a6226f7be032bfedc23b1261093c0374e3e176fb374818f8a38b015517c8bfc3cc1326967760bdeaac09e154e115826022cdcea75f944d61a7e724721a',
user: {
username: "......." /* 혹은 email: "...." */
} } ],
id: '1' }
형식으로 보내면 되겠다.
코드를 써보면
if dataJSON.msg is 'ready'
console.log '>> method beginPasswordExchange'
s = new srp.Client password
request = s.startExchange()
if typeof selector is 'string'
selector =
if ~selector.indexOf("@")
then email: selector
else username: selector
request.user = selector
sendObject =
msg: 'method',
method: 'beginPasswordExchange',
params: [request]
id: (++nextid).toString()
ws.send JSON.stringify sendObject
ready 이후에 이런식으로 써주면 되겠다. id는 1 넣으니 Malformed method invocation 오류가 나니 sequence 값을 계속 사용하고 있다.
돌려보니
>> method beginPasswordExchange
{ msg: 'updated', methods: [ '2' ] }
{ msg: 'result',
id: '2',
result:
{ identity: 'YzHuNjbsWJm5KvDce',
salt: 'sre6wg5ENP2FFNc42',
B: '6bd07e3539b211ad523e38509501becba435618e25d6bd3f55852311a4c8d5a49cc0b29ffa8ccc28d3122a12b6ee20fefa01fd313fbe92c4200156e7faa7c21e3a43b3949fc7feaba9843c858f3144d92994261e7a86f9154593ec795c7725bf73e8e4fa2febda2a4fcb8bb84aa248a2ad2bb1c31d13bdc1bf025e3deec813aa' } }
하지만 이게 전부는 아니다.
서버에 갔다와서 해쉬를 받아오는 부분이라 유저명만 체크한다고 봐도 된다. 암호는 결과 값을 기준으로 확인해야함.
login method를 쏴보자.
{
"msg":"method",
"method":"login",
"params":[
{
"srp":{
"M":"e3e18d009a23a2f560e8eb157b6eca9d686dc4f95e2f0381ba9a8fb8dd4fa9de"
}
}
],
"id":"2"
}
분석해보니 이런 내용이 websocket 나왔었다.
일단 여기까지 별 어려움 없이 잘 왔다.
어짜피 한 password 방식일때인 경우만 분석해봤는데
다른 경우도 크게 다르지 않을 거라고 생각한다.
전체 소스는 gist(https://gist.github.com/acidsound/6330360)에 올려놓겠다.
nextid = 0
connected = false;
ws = require 'ws'
## srp library from https://github.com/meteor/meteor/tree/devel/packages/srp
srp = require './lib/srp.js'
isLogin = false
## id/pass
selector = '<ID>'
password = '<PASS>'
s = new srp.Client password
ws = new ws 'ws://localhost:3000/websocket'
ws.on 'open', ->
console.log "open socket"
ws.send JSON.stringify
msg: 'connect'
version: 'pre1'
support: ['pre1']
ws.on 'message', (data, flags)->
dataJSON = JSON.parse data
console.log dataJSON
if dataJSON.msg is 'connected'
connected = true
ws.send JSON.stringify
msg: 'sub'
id: (++nextid).toString()
name: 'meteor.loginServiceConfiguration'
if dataJSON.msg is 'ready'
if not isLogin
console.log '>> method beginPasswordExchange'
request = s.startExchange()
if typeof selector is 'string'
selector =
if ~selector.indexOf("@")
then email: selector
else username: selector
request.user = selector
sendObject =
msg: 'method'
method: 'beginPasswordExchange'
params: [request]
id: (++nextid).toString()
ws.send JSON.stringify sendObject
if dataJSON.msg is 'result'
if not isLogin
console.log ">> checked username"
if !!dataJSON.error
console.log ">> username fail"
else
response = s.respondToChallenge dataJSON.result
sendObject =
msg: 'method'
method: 'login'
params: [
srp: response
]
id: (++nextid).toString()
console.log JSON.stringify sendObject
ws.send JSON.stringify sendObject
isLogin = true
else
## after login
if !!dataJSON.error
console.log ">>>> incorrect password"
else
if s.verifyConfirmation(HAMK:dataJSON.result.HAMK)
console.log ">>>> login success"
else
console.log ">>>> server is cheating!"
SRP(Secure Remote Password) 라는 프로토콜로 변환한다.
https://github.com/meteor/meteor/tree/devel/packages/srp
package.js 를 보면 biginteger 와 sha256 을 사용한다.
구현해야할 부분은 https://github.com/meteor/meteor/blob/devel/packages/accounts-password/password_client.js#L10
이 곳 참조.
password 를 가지고 다음과 같이.
s = new srp.Client password
request = s.startExchange()
if typeof selector == 'string'
selector =
if ~selector.indexof("@")
then username: selector
else email: selector
request.user = selector
beginPasswordExchange 를 시작하는 부분의 인자는 request 자체를 사용.
request 내용은 A를 키로 하는 SRP 암호문과 user를 키로하는 사용자명이 되겠다.
method 쏴준다. A에 srp로 암호화한 문자를 사용.
{ msg: 'method',
method: 'beginPasswordExchange',
params:
[ { A: '439284960ce6bc7c163262b5629a467cd06bb982432615ec526a1ed204d2f76a1a254faaab6c5c9309e120d708e3e46fe58d8c5017aedb85efb9670cfcbf8a8b2dd996a6226f7be032bfedc23b1261093c0374e3e176fb374818f8a38b015517c8bfc3cc1326967760bdeaac09e154e115826022cdcea75f944d61a7e724721a',
user: {
username: "......." /* 혹은 email: "...." */
} } ],
id: '1' }
형식으로 보내면 되겠다.
코드를 써보면
if dataJSON.msg is 'ready'
console.log '>> method beginPasswordExchange'
s = new srp.Client password
request = s.startExchange()
if typeof selector is 'string'
selector =
if ~selector.indexOf("@")
then email: selector
else username: selector
request.user = selector
sendObject =
msg: 'method',
method: 'beginPasswordExchange',
params: [request]
id: (++nextid).toString()
ws.send JSON.stringify sendObject
ready 이후에 이런식으로 써주면 되겠다. id는 1 넣으니 Malformed method invocation 오류가 나니 sequence 값을 계속 사용하고 있다.
돌려보니
>> method beginPasswordExchange
{ msg: 'updated', methods: [ '2' ] }
{ msg: 'result',
id: '2',
result:
{ identity: 'YzHuNjbsWJm5KvDce',
salt: 'sre6wg5ENP2FFNc42',
B: '6bd07e3539b211ad523e38509501becba435618e25d6bd3f55852311a4c8d5a49cc0b29ffa8ccc28d3122a12b6ee20fefa01fd313fbe92c4200156e7faa7c21e3a43b3949fc7feaba9843c858f3144d92994261e7a86f9154593ec795c7725bf73e8e4fa2febda2a4fcb8bb84aa248a2ad2bb1c31d13bdc1bf025e3deec813aa' } }
하지만 이게 전부는 아니다.
서버에 갔다와서 해쉬를 받아오는 부분이라 유저명만 체크한다고 봐도 된다. 암호는 결과 값을 기준으로 확인해야함.
login method를 쏴보자.
{
"msg":"method",
"method":"login",
"params":[
{
"srp":{
"M":"e3e18d009a23a2f560e8eb157b6eca9d686dc4f95e2f0381ba9a8fb8dd4fa9de"
}
}
],
"id":"2"
}
분석해보니 이런 내용이 websocket 나왔었다.
일단 여기까지 별 어려움 없이 잘 왔다.
어짜피 한 password 방식일때인 경우만 분석해봤는데
다른 경우도 크게 다르지 않을 거라고 생각한다.
전체 소스는 gist(https://gist.github.com/acidsound/6330360)에 올려놓겠다.
nextid = 0
connected = false;
ws = require 'ws'
## srp library from https://github.com/meteor/meteor/tree/devel/packages/srp
srp = require './lib/srp.js'
isLogin = false
## id/pass
selector = '<ID>'
password = '<PASS>'
s = new srp.Client password
ws = new ws 'ws://localhost:3000/websocket'
ws.on 'open', ->
console.log "open socket"
ws.send JSON.stringify
msg: 'connect'
version: 'pre1'
support: ['pre1']
ws.on 'message', (data, flags)->
dataJSON = JSON.parse data
console.log dataJSON
if dataJSON.msg is 'connected'
connected = true
ws.send JSON.stringify
msg: 'sub'
id: (++nextid).toString()
name: 'meteor.loginServiceConfiguration'
if dataJSON.msg is 'ready'
if not isLogin
console.log '>> method beginPasswordExchange'
request = s.startExchange()
if typeof selector is 'string'
selector =
if ~selector.indexOf("@")
then email: selector
else username: selector
request.user = selector
sendObject =
msg: 'method'
method: 'beginPasswordExchange'
params: [request]
id: (++nextid).toString()
ws.send JSON.stringify sendObject
if dataJSON.msg is 'result'
if not isLogin
console.log ">> checked username"
if !!dataJSON.error
console.log ">> username fail"
else
response = s.respondToChallenge dataJSON.result
sendObject =
msg: 'method'
method: 'login'
params: [
srp: response
]
id: (++nextid).toString()
console.log JSON.stringify sendObject
ws.send JSON.stringify sendObject
isLogin = true
else
## after login
if !!dataJSON.error
console.log ">>>> incorrect password"
else
if s.verifyConfirmation(HAMK:dataJSON.result.HAMK)
console.log ">>>> login success"
else
console.log ">>>> server is cheating!"
댓글
댓글 쓰기