Toggle navigation
Toggle navigation
此项目
正在载入...
Sign in
胡斌
/
srs
转到一个项目
Toggle navigation
项目
群组
代码片段
帮助
Toggle navigation pinning
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
winlin
2014-11-29 16:17:07 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
4b9875e279c73c5fac53f02e0a69abe7bbc67f47
4b9875e2
1 parent
5d883e2e
for bug #235, use strategy to implements the schema0 and schema1.
显示空白字符变更
内嵌
并排对比
正在显示
2 个修改的文件
包含
566 行增加
和
243 行删除
trunk/src/rtmp/srs_protocol_handshake.cpp
trunk/src/rtmp/srs_protocol_handshake.hpp
trunk/src/rtmp/srs_protocol_handshake.cpp
查看文件 @
4b9875e
...
...
@@ -638,261 +638,273 @@ namespace _srs_internal
return
bytes
;
}
c
2s2
::
c2s2
()
c
1s1_strategy
::
c1s1_strategy
()
{
srs_random_generate
(
random
,
1504
);
}
int
size
=
snprintf
(
random
,
1504
,
"%s"
,
RTMP_SIG_SRS_HANDSHAKE
);
srs_assert
(
++
size
<
1504
);
snprintf
(
random
+
1504
-
size
,
size
,
"%s"
,
RTMP_SIG_SRS_HANDSHAKE
);
c1s1_strategy
::~
c1s1_strategy
()
{
}
srs_random_generate
(
digest
,
32
);
c1s1_strategy_schema0
::
c1s1_strategy_schema0
()
{
key
.
init
();
digest
.
init
();
}
c
2s2
::~
c2s2
()
c
1s1_strategy_schema0
::~
c1s1_strategy_schema0
()
{
key
.
free
();
digest
.
free
();
}
void
c2s2
::
dump
(
char
*
_c2s2
)
srs_schema_type
c1s1_strategy_schema0
::
schema
(
)
{
memcpy
(
_c2s2
,
random
,
1504
);
memcpy
(
_c2s2
+
1504
,
digest
,
32
);
return
srs_schema0
;
}
void
c2s2
::
parse
(
char
*
_c2s2
)
char
*
c1s1_strategy_schema0
::
get_digest
(
)
{
memcpy
(
random
,
_c2s2
,
1504
);
memcpy
(
digest
,
_c2s2
+
1504
,
32
);
return
digest
.
digest
;
}
int
c2s2
::
c2_create
(
c1s1
*
s1
)
void
c1s1_strategy_schema0
::
dump
(
c1s1
*
owner
,
char
*
_c1s1
)
{
srs_schema0_copy_to
(
_c1s1
,
true
,
owner
->
time
,
owner
->
version
,
&
key
,
&
digest
);
}
int
c1s1_strategy_schema0
::
parse
(
char
*
_c1s1
)
{
int
ret
=
ERROR_SUCCESS
;
char
temp_key
[
__SRS_OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
SrsGenuineFPKey
,
62
,
s1
->
get_digest
(),
32
,
temp_key
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create c2 temp key failed. ret=%d"
,
ret
);
if
((
ret
=
key
.
parse
(
_c1s1
+
8
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"parse the c1 key failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"generate c2 temp key success."
);
char
_digest
[
__SRS_OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
temp_key
,
32
,
random
,
1504
,
_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create c2 digest failed. ret=%d"
,
ret
);
if
((
ret
=
digest
.
parse
(
_c1s1
+
8
+
764
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"parse the c1 digest failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"generate c2 digest success."
);
memcpy
(
digest
,
_digest
,
32
);
srs_verbose
(
"parse c1 key-digest success"
);
return
ret
;
}
int
c
2s2
::
c2_validate
(
c1s1
*
s1
,
bool
&
is_valid
)
int
c
1s1_strategy_schema0
::
c1_create
(
c1s1
*
owner
)
{
is_valid
=
false
;
int
ret
=
ERROR_SUCCESS
;
char
temp_key
[
__SRS_OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
SrsGenuineFPKey
,
62
,
s1
->
get_digest
(),
32
,
temp_key
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create c2 temp key failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"generate c2 temp key success."
);
// generate digest
char
*
c1_digest
=
NULL
;
char
_digest
[
__SRS_OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
temp_key
,
32
,
random
,
1504
,
_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create c2 digest failed. ret=%d"
,
ret
);
if
((
ret
=
calc_c1_digest
(
owner
,
c1_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"sign c1 error, failed to calc digest. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"generate c2 digest success."
);
is_valid
=
srs_bytes_equals
(
digest
,
_digest
,
32
);
srs_assert
(
c1_digest
!=
NULL
);
SrsAutoFree
(
char
,
c1_digest
);
memcpy
(
digest
.
digest
,
c1_digest
,
32
);
return
ret
;
}
int
c
2s2
::
s2_create
(
c1s1
*
c1
)
int
c
1s1_strategy_schema0
::
c1_validate_digest
(
c1s1
*
owner
,
bool
&
is_valid
)
{
int
ret
=
ERROR_SUCCESS
;
char
temp_key
[
__SRS_OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
SrsGenuineFMSKey
,
68
,
c1
->
get_digest
(),
32
,
temp_key
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create s2 temp key failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"generate s2 temp key success."
);
char
*
c1_digest
=
NULL
;
char
_digest
[
__SRS_OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
temp_key
,
32
,
random
,
1504
,
_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create s2 digest failed. ret=%d"
,
ret
);
if
((
ret
=
calc_c1_digest
(
owner
,
c1_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"validate c1 error, failed to calc digest. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"generate s2 digest success."
);
memcpy
(
digest
,
_digest
,
32
);
srs_assert
(
c1_digest
!=
NULL
);
SrsAutoFree
(
char
,
c1_digest
);
is_valid
=
srs_bytes_equals
(
digest
.
digest
,
c1_digest
,
32
);
return
ret
;
}
int
c
2s2
::
s2_validate
(
c1s1
*
c1
,
bool
&
is_valid
)
int
c
1s1_strategy_schema0
::
s1_create
(
c1s1
*
owner
)
{
is_valid
=
false
;
int
ret
=
ERROR_SUCCESS
;
char
temp_key
[
__SRS_OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
SrsGenuineFMSKey
,
68
,
c1
->
get_digest
(),
32
,
temp_key
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create s2 temp key failed. ret=%d"
,
ret
);
SrsDH
dh
;
// ensure generate 128bytes public key.
if
((
ret
=
dh
.
initialize
(
true
))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
srs_verbose
(
"generate s2 temp key success."
);
char
_digest
[
__SRS_OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
temp_key
,
32
,
random
,
1504
,
_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create s2 digest failed. ret=%d"
,
ret
);
// directly generate the public key.
// @see: https://github.com/winlinvip/simple-rtmp-server/issues/148
int
pkey_size
=
128
;
// TODO: FIXME: use c1 public key to calc the shared key.
if
((
ret
=
dh
.
copy_public_key
(
key
.
key
,
pkey_size
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"calc s1 key failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"generate s2 digest success."
);
is_valid
=
srs_bytes_equals
(
digest
,
_digest
,
32
);
srs_assert
(
pkey_size
==
128
);
srs_verbose
(
"calc s1 key success."
);
char
*
s1_digest
=
NULL
;
if
((
ret
=
calc_s1_digest
(
owner
,
s1_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"calc s1 digest failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"calc s1 digest success."
);
// TODO: FIXME: move to the right position.
c1s1
::
c1s1
()
{
schema
=
srs_schema_invalid
;
}
c1s1
::~
c1s1
()
{
destroy_blocks
();
}
srs_assert
(
s1_digest
!=
NULL
);
SrsAutoFree
(
char
,
s1_digest
);
char
*
c1s1
::
get_digest
()
{
srs_assert
(
schema
!=
srs_schema_invalid
);
memcpy
(
digest
.
digest
,
s1_digest
,
32
);
srs_verbose
(
"copy s1 key success."
);
if
(
schema
==
srs_schema0
)
{
return
block1
.
digest
.
digest
;
}
else
{
return
block0
.
digest
.
digest
;
}
return
ret
;
}
void
c1s1
::
dump
(
char
*
_c1s1
)
int
c1s1_strategy_schema0
::
s1_validate_digest
(
c1s1
*
owner
,
bool
&
is_valid
)
{
srs_assert
(
schema
!=
srs_schema_invalid
)
;
int
ret
=
ERROR_SUCCESS
;
if
(
schema
==
srs_schema0
)
{
srs_schema0_copy_to
(
_c1s1
,
true
,
time
,
version
,
&
block0
.
key
,
&
block1
.
digest
);
}
else
{
srs_schema1_copy_to
(
_c1s1
,
true
,
time
,
version
,
&
block0
.
digest
,
&
block1
.
key
);
char
*
s1_digest
=
NULL
;
if
((
ret
=
calc_s1_digest
(
owner
,
s1_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"validate s1 error, failed to calc digest. ret=%d"
,
ret
);
return
ret
;
}
srs_assert
(
s1_digest
!=
NULL
);
SrsAutoFree
(
char
,
s1_digest
);
is_valid
=
srs_bytes_equals
(
digest
.
digest
,
s1_digest
,
32
);
return
ret
;
}
int
c1s1
::
parse
(
char
*
_c1s1
,
srs_schema_type
_schema
)
int
c1s1
_strategy_schema0
::
calc_c1_digest
(
c1s1
*
owner
,
char
*&
c1_digest
)
{
int
ret
=
ERROR_SUCCESS
;
if
(
_schema
==
srs_schema_invalid
)
{
ret
=
ERROR_RTMP_CH_SCHEMA
;
srs_error
(
"parse c1 failed. invalid schema=%d, ret=%d"
,
_schema
,
ret
);
char
*
c1s1_joined_bytes
=
NULL
;
c1s1_joined_bytes
=
srs_bytes_join_schema0
(
owner
->
time
,
owner
->
version
,
&
key
,
&
digest
);
srs_assert
(
c1s1_joined_bytes
!=
NULL
);
SrsAutoFree
(
char
,
c1s1_joined_bytes
);
c1_digest
=
new
char
[
__SRS_OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
SrsGenuineFPKey
,
30
,
c1s1_joined_bytes
,
1536
-
32
,
c1_digest
))
!=
ERROR_SUCCESS
)
{
srs_freep
(
c1_digest
);
srs_error
(
"calc digest for c1 failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"digest calculated for c1"
);
destroy_blocks
();
return
ret
;
}
int
c1s1_strategy_schema0
::
calc_s1_digest
(
c1s1
*
owner
,
char
*&
s1_digest
)
{
int
ret
=
ERROR_SUCCESS
;
char
*
c1s1_joined_bytes
=
NULL
;
time
=
__srs_stream_read_4bytes
(
_c1s1
);
version
=
__srs_stream_read_4bytes
(
_c1s1
+
4
);
// client c1 version
c1s1_joined_bytes
=
srs_bytes_join_schema0
(
owner
->
time
,
owner
->
version
,
&
key
,
&
digest
);
if
(
_schema
==
srs_schema0
)
{
if
((
ret
=
block0
.
key
.
parse
(
_c1s1
+
8
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"parse the c1 key failed. ret=%d"
,
ret
);
srs_assert
(
c1s1_joined_bytes
!=
NULL
);
SrsAutoFree
(
char
,
c1s1_joined_bytes
);
s1_digest
=
new
char
[
__SRS_OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
SrsGenuineFMSKey
,
36
,
c1s1_joined_bytes
,
1536
-
32
,
s1_digest
))
!=
ERROR_SUCCESS
)
{
srs_freep
(
s1_digest
);
srs_error
(
"calc digest for s1 failed. ret=%d"
,
ret
);
return
ret
;
}
if
((
ret
=
block1
.
digest
.
parse
(
_c1s1
+
8
+
764
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"parse the c1 digest failed. ret=%d"
,
ret
);
srs_verbose
(
"digest calculated for s1"
);
return
ret
;
}
srs_verbose
(
"parse c1 key-digest success"
);
}
else
if
(
_schema
==
srs_schema1
)
{
if
((
ret
=
block0
.
digest
.
parse
(
_c1s1
+
8
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"parse the c1 key failed. ret=%d"
,
ret
);
return
ret
;
c1s1_strategy_schema1
::
c1s1_strategy_schema1
()
{
key
.
init
();
digest
.
init
();
}
if
((
ret
=
block1
.
key
.
parse
(
_c1s1
+
8
+
764
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"parse the c1 digest failed. ret=%d"
,
ret
);
return
ret
;
c1s1_strategy_schema1
::~
c1s1_strategy_schema1
()
{
key
.
free
();
digest
.
free
();
}
srs_verbose
(
"parse c1 digest-key success"
);
}
else
{
ret
=
ERROR_RTMP_CH_SCHEMA
;
srs_error
(
"parse c1 failed. invalid schema=%d, ret=%d"
,
_schema
,
ret
);
return
ret
;
srs_schema_type
c1s1_strategy_schema1
::
schema
()
{
return
srs_schema1
;
}
schema
=
_schema
;
char
*
c1s1_strategy_schema1
::
get_digest
()
{
return
digest
.
digest
;
}
return
ret
;
void
c1s1_strategy_schema1
::
dump
(
c1s1
*
owner
,
char
*
_c1s1
)
{
srs_schema0_copy_to
(
_c1s1
,
true
,
owner
->
time
,
owner
->
version
,
&
key
,
&
digest
);
}
int
c1s1
::
c1_create
(
srs_schema_type
_schema
)
int
c1s1
_strategy_schema1
::
parse
(
char
*
_c1s1
)
{
int
ret
=
ERROR_SUCCESS
;
if
(
_schema
==
srs_schema_invalid
)
{
ret
=
ERROR_RTMP_CH_SCHEMA
;
srs_error
(
"create c1 failed. invalid schema=%d, ret=%d"
,
_schema
,
ret
);
if
((
ret
=
digest
.
parse
(
_c1s1
+
8
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"parse the c1 digest failed. ret=%d"
,
ret
);
return
ret
;
}
destroy_blocks
();
if
((
ret
=
key
.
parse
(
_c1s1
+
8
+
764
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"parse the c1 key failed. ret=%d"
,
ret
);
return
ret
;
}
// client c1 time and version
time
=
::
time
(
NULL
);
version
=
0x80000702
;
// client c1 version
srs_verbose
(
"parse c1 digest-key success"
);
// generate signature by schema
if
(
_schema
==
srs_schema0
)
{
block0
.
key
.
init
();
block1
.
digest
.
init
();
}
else
{
block0
.
digest
.
init
();
block1
.
key
.
init
();
return
ret
;
}
schema
=
_schema
;
int
c1s1_strategy_schema1
::
c1_create
(
c1s1
*
owner
)
{
int
ret
=
ERROR_SUCCESS
;
// generate digest
char
*
digest
=
NULL
;
char
*
c1_
digest
=
NULL
;
if
((
ret
=
calc_c1_digest
(
digest
))
!=
ERROR_SUCCESS
)
{
if
((
ret
=
calc_c1_digest
(
owner
,
c1_
digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"sign c1 error, failed to calc digest. ret=%d"
,
ret
);
return
ret
;
}
srs_assert
(
digest
!=
NULL
);
SrsAutoFree
(
char
,
digest
);
srs_assert
(
c1_digest
!=
NULL
);
SrsAutoFree
(
char
,
c1_digest
);
if
(
schema
==
srs_schema0
)
{
memcpy
(
block1
.
digest
.
digest
,
digest
,
32
);
}
else
{
memcpy
(
block0
.
digest
.
digest
,
digest
,
32
);
}
memcpy
(
digest
.
digest
,
c1_digest
,
32
);
return
ret
;
}
int
c1s1
::
c1_validate_digest
(
bool
&
is_valid
)
int
c1s1
_strategy_schema1
::
c1_validate_digest
(
c1s1
*
owner
,
bool
&
is_valid
)
{
is_valid
=
false
;
int
ret
=
ERROR_SUCCESS
;
char
*
c1_digest
=
NULL
;
if
((
ret
=
calc_c1_digest
(
c1_digest
))
!=
ERROR_SUCCESS
)
{
if
((
ret
=
calc_c1_digest
(
owner
,
c1_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"validate c1 error, failed to calc digest. ret=%d"
,
ret
);
return
ret
;
}
...
...
@@ -900,163 +912,241 @@ namespace _srs_internal
srs_assert
(
c1_digest
!=
NULL
);
SrsAutoFree
(
char
,
c1_digest
);
if
(
schema
==
srs_schema0
)
{
is_valid
=
srs_bytes_equals
(
block1
.
digest
.
digest
,
c1_digest
,
32
);
}
else
{
is_valid
=
srs_bytes_equals
(
block0
.
digest
.
digest
,
c1_digest
,
32
);
}
is_valid
=
srs_bytes_equals
(
digest
.
digest
,
c1_digest
,
32
);
return
ret
;
}
int
c1s1
::
s1_validate_digest
(
bool
&
is_valid
)
int
c1s1
_strategy_schema1
::
s1_create
(
c1s1
*
owner
)
{
is_valid
=
false
;
int
ret
=
ERROR_SUCCESS
;
char
*
s1_digest
=
NULL
;
SrsDH
dh
;
if
((
ret
=
calc_s1_digest
(
s1_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"validate s1 error, failed to calc digest. ret=%d"
,
ret
);
// ensure generate 128bytes public key.
if
((
ret
=
dh
.
initialize
(
true
))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
// directly generate the public key.
// @see: https://github.com/winlinvip/simple-rtmp-server/issues/148
int
pkey_size
=
128
;
if
((
ret
=
dh
.
copy_public_key
(
key
.
key
,
pkey_size
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"calc s1 key failed. ret=%d"
,
ret
);
return
ret
;
}
srs_assert
(
pkey_size
==
128
);
srs_verbose
(
"calc s1 key success."
);
char
*
s1_digest
=
NULL
;
if
((
ret
=
calc_s1_digest
(
owner
,
s1_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"calc s1 digest failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"calc s1 digest success."
);
srs_assert
(
s1_digest
!=
NULL
);
SrsAutoFree
(
char
,
s1_digest
);
if
(
schema
==
srs_schema0
)
{
is_valid
=
srs_bytes_equals
(
block1
.
digest
.
digest
,
s1_digest
,
32
);
}
else
{
is_valid
=
srs_bytes_equals
(
block0
.
digest
.
digest
,
s1_digest
,
32
);
}
memcpy
(
digest
.
digest
,
s1_digest
,
32
);
srs_verbose
(
"copy s1 key success."
);
return
ret
;
}
int
c1s1
::
s1_create
(
c1s1
*
c1
)
int
c1s1
_strategy_schema1
::
s1_validate_digest
(
c1s1
*
owner
,
bool
&
is_valid
)
{
int
ret
=
ERROR_SUCCESS
;
if
(
c1
->
schema
==
srs_schema_invalid
)
{
ret
=
ERROR_RTMP_CH_SCHEMA
;
srs_error
(
"create s1 failed. invalid schema=%d, ret=%d"
,
c1
->
schema
,
ret
);
char
*
s1_digest
=
NULL
;
if
((
ret
=
calc_s1_digest
(
owner
,
s1_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"validate s1 error, failed to calc digest. ret=%d"
,
ret
);
return
ret
;
}
destroy_blocks
();
schema
=
c1
->
schema
;
srs_assert
(
s1_digest
!=
NULL
);
SrsAutoFree
(
char
,
s1_digest
);
time
=
::
time
(
NULL
);
version
=
0x01000504
;
// server s1 version
is_valid
=
srs_bytes_equals
(
digest
.
digest
,
s1_digest
,
32
);
SrsDH
dh
;
// ensure generate 128bytes public key.
if
((
ret
=
dh
.
initialize
(
true
))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
if
(
schema
==
srs_schema0
)
{
block0
.
key
.
init
();
block1
.
digest
.
init
();
int
c1s1_strategy_schema1
::
calc_c1_digest
(
c1s1
*
owner
,
char
*&
c1_digest
)
{
int
ret
=
ERROR_SUCCESS
;
// directly generate the public key.
// @see: https://github.com/winlinvip/simple-rtmp-server/issues/148
int
pkey_size
=
128
;
if
((
ret
=
dh
.
copy_public_key
(
block0
.
key
.
key
,
pkey_size
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"calc s1 key failed. ret=%d"
,
ret
);
char
*
c1s1_joined_bytes
=
NULL
;
c1s1_joined_bytes
=
srs_bytes_join_schema1
(
owner
->
time
,
owner
->
version
,
&
digest
,
&
key
);
srs_assert
(
c1s1_joined_bytes
!=
NULL
);
SrsAutoFree
(
char
,
c1s1_joined_bytes
);
c1_digest
=
new
char
[
__SRS_OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
SrsGenuineFPKey
,
30
,
c1s1_joined_bytes
,
1536
-
32
,
c1_digest
))
!=
ERROR_SUCCESS
)
{
srs_freep
(
c1_digest
);
srs_error
(
"calc digest for c1 failed. ret=%d"
,
ret
);
return
ret
;
}
srs_assert
(
pkey_size
==
128
);
}
else
{
block0
.
digest
.
init
();
block1
.
key
.
init
();
srs_verbose
(
"digest calculated for c1"
);
// directly generate the public key.
// @see: https://github.com/winlinvip/simple-rtmp-server/issues/148
int
pkey_size
=
128
;
if
((
ret
=
dh
.
copy_public_key
(
block1
.
key
.
key
,
pkey_size
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"calc s1 key failed. ret=%d"
,
ret
);
return
ret
;
}
srs_assert
(
pkey_size
==
128
);
int
c1s1_strategy_schema1
::
calc_s1_digest
(
c1s1
*
owner
,
char
*&
s1_digest
)
{
int
ret
=
ERROR_SUCCESS
;
char
*
c1s1_joined_bytes
=
NULL
;
c1s1_joined_bytes
=
srs_bytes_join_schema1
(
owner
->
time
,
owner
->
version
,
&
digest
,
&
key
);
srs_assert
(
c1s1_joined_bytes
!=
NULL
);
SrsAutoFree
(
char
,
c1s1_joined_bytes
);
s1_digest
=
new
char
[
__SRS_OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
SrsGenuineFMSKey
,
36
,
c1s1_joined_bytes
,
1536
-
32
,
s1_digest
))
!=
ERROR_SUCCESS
)
{
srs_freep
(
s1_digest
);
srs_error
(
"calc digest for s1 failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"
calc s1 key success.
"
);
srs_verbose
(
"
digest calculated for s1
"
);
char
*
s1_digest
=
NULL
;
if
((
ret
=
calc_s1_digest
(
s1_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"calc s1 digest failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"calc s1 digest success."
);
srs_assert
(
s1_digest
!=
NULL
);
SrsAutoFree
(
char
,
s1_digest
);
c2s2
::
c2s2
()
{
srs_random_generate
(
random
,
1504
);
if
(
schema
==
srs_schema0
)
{
memcpy
(
block1
.
digest
.
digest
,
s1_digest
,
32
);
}
else
{
memcpy
(
block0
.
digest
.
digest
,
s1_digest
,
32
);
int
size
=
snprintf
(
random
,
1504
,
"%s"
,
RTMP_SIG_SRS_HANDSHAKE
);
srs_assert
(
++
size
<
1504
);
snprintf
(
random
+
1504
-
size
,
size
,
"%s"
,
RTMP_SIG_SRS_HANDSHAKE
);
srs_random_generate
(
digest
,
32
);
}
srs_verbose
(
"copy s1 key success."
);
return
ret
;
c2s2
::~
c2s2
()
{
}
void
c2s2
::
dump
(
char
*
_c2s2
)
{
memcpy
(
_c2s2
,
random
,
1504
);
memcpy
(
_c2s2
+
1504
,
digest
,
32
);
}
int
c1s1
::
calc_s1_digest
(
char
*&
digest
)
void
c2s2
::
parse
(
char
*
_c2s2
)
{
memcpy
(
random
,
_c2s2
,
1504
);
memcpy
(
digest
,
_c2s2
+
1504
,
32
);
}
int
c2s2
::
c2_create
(
c1s1
*
s1
)
{
int
ret
=
ERROR_SUCCESS
;
srs_assert
(
schema
==
srs_schema0
||
schema
==
srs_schema1
);
char
temp_key
[
__SRS_OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
SrsGenuineFPKey
,
62
,
s1
->
get_digest
(),
32
,
temp_key
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create c2 temp key failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"generate c2 temp key success."
);
char
*
c1s1_joined_bytes
=
NULL
;
char
_digest
[
__SRS_OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
temp_key
,
32
,
random
,
1504
,
_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create c2 digest failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"generate c2 digest success."
);
if
(
schema
==
srs_schema0
)
{
c1s1_joined_bytes
=
srs_bytes_join_schema0
(
time
,
version
,
&
block0
.
key
,
&
block1
.
digest
);
}
else
{
c1s1_joined_bytes
=
srs_bytes_join_schema1
(
time
,
version
,
&
block0
.
digest
,
&
block1
.
key
);
memcpy
(
digest
,
_digest
,
32
);
return
ret
;
}
srs_assert
(
c1s1_joined_bytes
!=
NULL
);
SrsAutoFree
(
char
,
c1s1_joined_bytes
);
int
c2s2
::
c2_validate
(
c1s1
*
s1
,
bool
&
is_valid
)
{
is_valid
=
false
;
int
ret
=
ERROR_SUCCESS
;
digest
=
new
char
[
__SRS_OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
SrsGenuineFMSKey
,
36
,
c1s1_joined_bytes
,
1536
-
32
,
digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"calc digest for s1 failed. ret=%d"
,
ret
);
char
temp_key
[
__SRS_OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
SrsGenuineFPKey
,
62
,
s1
->
get_digest
(),
32
,
temp_key
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create c2 temp key failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"digest calculated for s1"
);
srs_verbose
(
"generate c2 temp key success."
);
char
_digest
[
__SRS_OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
temp_key
,
32
,
random
,
1504
,
_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create c2 digest failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"generate c2 digest success."
);
is_valid
=
srs_bytes_equals
(
digest
,
_digest
,
32
);
return
ret
;
}
int
c
1s1
::
calc_c1_digest
(
char
*&
digest
)
int
c
2s2
::
s2_create
(
c1s1
*
c1
)
{
int
ret
=
ERROR_SUCCESS
;
srs_assert
(
schema
==
srs_schema0
||
schema
==
srs_schema1
);
char
temp_key
[
__SRS_OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
SrsGenuineFMSKey
,
68
,
c1
->
get_digest
(),
32
,
temp_key
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create s2 temp key failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"generate s2 temp key success."
);
char
_digest
[
__SRS_OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
temp_key
,
32
,
random
,
1504
,
_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create s2 digest failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"generate s2 digest success."
);
char
*
c1s1_joined_bytes
=
NULL
;
memcpy
(
digest
,
_digest
,
32
)
;
if
(
schema
==
srs_schema0
)
{
c1s1_joined_bytes
=
srs_bytes_join_schema0
(
time
,
version
,
&
block0
.
key
,
&
block1
.
digest
);
}
else
{
c1s1_joined_bytes
=
srs_bytes_join_schema1
(
time
,
version
,
&
block0
.
digest
,
&
block1
.
key
);
return
ret
;
}
srs_assert
(
c1s1_joined_bytes
!=
NULL
);
SrsAutoFree
(
char
,
c1s1_joined_bytes
);
int
c2s2
::
s2_validate
(
c1s1
*
c1
,
bool
&
is_valid
)
{
is_valid
=
false
;
int
ret
=
ERROR_SUCCESS
;
digest
=
new
char
[
__SRS_OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
SrsGenuineFPKey
,
30
,
c1s1_joined_bytes
,
1536
-
32
,
digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"calc digest for c1 failed. ret=%d"
,
ret
);
char
temp_key
[
__SRS_OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
SrsGenuineFMSKey
,
68
,
c1
->
get_digest
(),
32
,
temp_key
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create s2 temp key failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"digest calculated for c1"
);
srs_verbose
(
"generate s2 temp key success."
);
char
_digest
[
__SRS_OpensslHashSize
];
if
((
ret
=
openssl_HMACsha256
(
temp_key
,
32
,
random
,
1504
,
_digest
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"create s2 digest failed. ret=%d"
,
ret
);
return
ret
;
}
srs_verbose
(
"generate s2 digest success."
);
is_valid
=
srs_bytes_equals
(
digest
,
_digest
,
32
);
return
ret
;
}
// TODO: FIXME: move to the right position.
c1s1
::
c1s1
()
{
payload
=
NULL
;
}
c1s1
::~
c1s1
()
{
srs_freep
(
payload
);
/*
void c1s1::destroy_blocks()
{
if (schema == srs_schema_invalid) {
...
...
@@ -1070,6 +1160,110 @@ namespace _srs_internal
block0.digest.free();
block1.key.free();
}
}*/
}
srs_schema_type
c1s1
::
schema
()
{
srs_assert
(
payload
!=
NULL
);
return
payload
->
schema
();
}
char
*
c1s1
::
get_digest
()
{
srs_assert
(
payload
!=
NULL
);
return
payload
->
get_digest
();
}
void
c1s1
::
dump
(
char
*
_c1s1
)
{
srs_assert
(
payload
!=
NULL
);
return
payload
->
dump
(
this
,
_c1s1
);
}
int
c1s1
::
parse
(
char
*
_c1s1
,
srs_schema_type
schema
)
{
int
ret
=
ERROR_SUCCESS
;
if
(
schema
!=
srs_schema0
&&
schema
!=
srs_schema1
)
{
ret
=
ERROR_RTMP_CH_SCHEMA
;
srs_error
(
"parse c1 failed. invalid schema=%d, ret=%d"
,
schema
,
ret
);
return
ret
;
}
time
=
__srs_stream_read_4bytes
(
_c1s1
);
version
=
__srs_stream_read_4bytes
(
_c1s1
+
4
);
// client c1 version
srs_freep
(
payload
);
if
(
schema
==
srs_schema0
)
{
payload
=
new
c1s1_strategy_schema0
();
}
else
{
payload
=
new
c1s1_strategy_schema1
();
}
return
payload
->
parse
(
_c1s1
);
}
int
c1s1
::
c1_create
(
srs_schema_type
schema
)
{
int
ret
=
ERROR_SUCCESS
;
if
(
schema
!=
srs_schema0
&&
schema
!=
srs_schema1
)
{
ret
=
ERROR_RTMP_CH_SCHEMA
;
srs_error
(
"create c1 failed. invalid schema=%d, ret=%d"
,
schema
,
ret
);
return
ret
;
}
// client c1 time and version
time
=
::
time
(
NULL
);
version
=
0x80000702
;
// client c1 version
// generate signature by schema
srs_freep
(
payload
);
if
(
schema
==
srs_schema0
)
{
payload
=
new
c1s1_strategy_schema0
();
}
else
{
payload
=
new
c1s1_strategy_schema1
();
}
return
payload
->
c1_create
(
this
);
}
int
c1s1
::
c1_validate_digest
(
bool
&
is_valid
)
{
is_valid
=
false
;
srs_assert
(
payload
);
return
payload
->
c1_validate_digest
(
this
,
is_valid
);
}
int
c1s1
::
s1_validate_digest
(
bool
&
is_valid
)
{
is_valid
=
false
;
srs_assert
(
payload
);
return
payload
->
s1_validate_digest
(
this
,
is_valid
);
}
int
c1s1
::
s1_create
(
c1s1
*
c1
)
{
int
ret
=
ERROR_SUCCESS
;
if
(
c1
->
schema
()
!=
srs_schema0
&&
c1
->
schema
()
!=
srs_schema1
)
{
ret
=
ERROR_RTMP_CH_SCHEMA
;
srs_error
(
"create s1 failed. invalid schema=%d, ret=%d"
,
c1
->
schema
(),
ret
);
return
ret
;
}
time
=
::
time
(
NULL
);
version
=
0x01000504
;
// server s1 version
srs_freep
(
payload
);
if
(
c1
->
schema
()
==
srs_schema0
)
{
payload
=
new
c1s1_strategy_schema0
();
}
else
{
payload
=
new
c1s1_strategy_schema1
();
}
return
payload
->
s1_create
(
this
);
}
}
...
...
@@ -1190,6 +1384,7 @@ int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrs
// decode c1
c1s1
c1
;
// try schema0.
// @remark, use schema0 to make flash player happy.
if
((
ret
=
c1
.
parse
(
hs_bytes
->
c0c1
+
1
,
srs_schema0
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"parse c1 schema%d error. ret=%d"
,
srs_schema0
,
ret
);
return
ret
;
...
...
@@ -1197,6 +1392,7 @@ int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrs
// try schema1
bool
is_valid
=
false
;
if
((
ret
=
c1
.
c1_validate_digest
(
is_valid
))
!=
ERROR_SUCCESS
||
!
is_valid
)
{
srs_info
(
"schema0 failed, try schema1."
);
if
((
ret
=
c1
.
parse
(
hs_bytes
->
c0c1
+
1
,
srs_schema1
))
!=
ERROR_SUCCESS
)
{
srs_error
(
"parse c1 schema%d error. ret=%d"
,
srs_schema1
,
ret
);
return
ret
;
...
...
@@ -1207,6 +1403,8 @@ int SrsComplexHandshake::handshake_with_client(SrsHandshakeBytes* hs_bytes, ISrs
srs_info
(
"all schema valid failed, try simple handshake. ret=%d"
,
ret
);
return
ret
;
}
}
else
{
srs_info
(
"schema0 is ok."
);
}
srs_verbose
(
"decode c1 success."
);
...
...
@@ -1321,7 +1519,7 @@ int SrsComplexHandshake::handshake_with_server(SrsHandshakeBytes* hs_bytes, ISrs
// verify s1s2
c1s1
s1
;
if
((
ret
=
s1
.
parse
(
hs_bytes
->
s0s1s2
+
1
,
c1
.
schema
))
!=
ERROR_SUCCESS
)
{
if
((
ret
=
s1
.
parse
(
hs_bytes
->
s0s1s2
+
1
,
c1
.
schema
()
))
!=
ERROR_SUCCESS
)
{
return
ret
;
}
...
...
trunk/src/rtmp/srs_protocol_handshake.hpp
查看文件 @
4b9875e
...
...
@@ -219,6 +219,121 @@ namespace _srs_internal
*/
char
*
srs_bytes_join_schema1
(
int32_t
time
,
int32_t
version
,
digest_block
*
digest
,
key_block
*
key
);
class
c1s1
;
/**
* the c1s1 strategy, use schema0 or schema1.
* the template method class to defines common behaviors,
* while the concrete class to implements in schema0 or schema1.
*/
class
c1s1_strategy
{
public
:
c1s1_strategy
();
virtual
~
c1s1_strategy
();
public
:
/**
* get the scema.
*/
virtual
srs_schema_type
schema
()
=
0
;
/**
* get the digest key.
*/
virtual
char
*
get_digest
()
=
0
;
/**
* copy to bytes.
*/
virtual
void
dump
(
c1s1
*
owner
,
char
*
_c1s1
)
=
0
;
/**
* server: parse the c1s1, discovery the key and digest by schema.
* use the c1_validate_digest() to valid the digest of c1.
*/
virtual
int
parse
(
char
*
_c1s1
)
=
0
;
public
:
/**
* client: create and sign c1 by schema.
* sign the c1, generate the digest.
* calc_c1_digest(c1, schema) {
* get c1s1-joined from c1 by specified schema
* digest-data = HMACsha256(c1s1-joined, FPKey, 30)
* return digest-data;
* }
* random fill 1536bytes c1 // also fill the c1-128bytes-key
* time = time() // c1[0-3]
* version = [0x80, 0x00, 0x07, 0x02] // c1[4-7]
* schema = choose schema0 or schema1
* digest-data = calc_c1_digest(c1, schema)
* copy digest-data to c1
*/
virtual
int
c1_create
(
c1s1
*
owner
)
=
0
;
/**
* server: validate the parsed c1 schema
*/
virtual
int
c1_validate_digest
(
c1s1
*
owner
,
bool
&
is_valid
)
=
0
;
/**
* server: create and sign the s1 from c1.
*/
virtual
int
s1_create
(
c1s1
*
owner
)
=
0
;
/**
* server: validate the parsed s1 schema
*/
virtual
int
s1_validate_digest
(
c1s1
*
owner
,
bool
&
is_valid
)
=
0
;
};
/**
* c1s1 schema0
* key: 764bytes
* digest: 764bytes
*/
class
c1s1_strategy_schema0
:
public
c1s1_strategy
{
private
:
key_block
key
;
digest_block
digest
;
public
:
c1s1_strategy_schema0
();
virtual
~
c1s1_strategy_schema0
();
public
:
virtual
srs_schema_type
schema
();
virtual
char
*
get_digest
();
virtual
void
dump
(
c1s1
*
owner
,
char
*
_c1s1
);
virtual
int
parse
(
char
*
_c1s1
);
virtual
int
c1_create
(
c1s1
*
owner
);
virtual
int
c1_validate_digest
(
c1s1
*
owner
,
bool
&
is_valid
);
virtual
int
s1_create
(
c1s1
*
owner
);
virtual
int
s1_validate_digest
(
c1s1
*
owner
,
bool
&
is_valid
);
private
:
virtual
int
calc_c1_digest
(
c1s1
*
owner
,
char
*&
c1_digest
);
virtual
int
calc_s1_digest
(
c1s1
*
owner
,
char
*&
s1_digest
);
};
/**
* c1s1 schema1
* digest: 764bytes
* key: 764bytes
*/
class
c1s1_strategy_schema1
:
public
c1s1_strategy
{
private
:
digest_block
digest
;
key_block
key
;
public
:
c1s1_strategy_schema1
();
virtual
~
c1s1_strategy_schema1
();
public
:
virtual
srs_schema_type
schema
();
virtual
char
*
get_digest
();
virtual
void
dump
(
c1s1
*
owner
,
char
*
_c1s1
);
virtual
int
parse
(
char
*
_c1s1
);
virtual
int
c1_create
(
c1s1
*
owner
);
virtual
int
c1_validate_digest
(
c1s1
*
owner
,
bool
&
is_valid
);
virtual
int
s1_create
(
c1s1
*
owner
);
virtual
int
s1_validate_digest
(
c1s1
*
owner
,
bool
&
is_valid
);
private
:
virtual
int
calc_c1_digest
(
c1s1
*
owner
,
char
*&
c1_digest
);
virtual
int
calc_s1_digest
(
c1s1
*
owner
,
char
*&
s1_digest
);
};
/**
* c1s1 schema0
* time: 4bytes
...
...
@@ -235,30 +350,20 @@ namespace _srs_internal
class
c1s1
{
public
:
union
block
{
key_block
key
;
digest_block
digest
;
};
// 4bytes
int32_t
time
;
// 4bytes
int32_t
version
;
// 764bytes
// if schema0, use key
// if schema1, use digest
block
block0
;
// 764bytes
// if schema0, use digest
// if schema1, use key
block
block1
;
// the logic schema
srs_schema_type
schema
;
// 764bytes+764bytes
c1s1_strategy
*
payload
;
c1s1
();
virtual
~
c1s1
();
/**
* get the scema.
*/
virtual
srs_schema_type
schema
();
/**
* get the digest key.
*/
virtual
char
*
get_digest
();
...
...
@@ -269,6 +374,7 @@ namespace _srs_internal
/**
* server: parse the c1s1, discovery the key and digest by schema.
* use the c1_validate_digest() to valid the digest of c1.
* use the s1_validate_digest() to valid the digest of s1.
*/
virtual
int
parse
(
char
*
_c1s1
,
srs_schema_type
_schema
);
...
...
@@ -294,16 +400,35 @@ namespace _srs_internal
virtual
int
c1_validate_digest
(
bool
&
is_valid
);
/**
* server: create and sign the s1 from c1.
* // decode c1 try schema0 then schema1
* c1-digest-data = get-c1-digest-data(schema0)
* if c1-digest-data equals to calc_c1_digest(c1, schema0) {
* c1-key-data = get-c1-key-data(schema0)
* schema = schema0
* } else {
* c1-digest-data = get-c1-digest-data(schema1)
* if c1-digest-data not equals to calc_c1_digest(c1, schema1) {
* switch to simple handshake.
* return
* }
* c1-key-data = get-c1-key-data(schema1)
* schema = schema1
* }
*
* // generate s1
* random fill 1536bytes s1
* time = time() // c1[0-3]
* version = [0x04, 0x05, 0x00, 0x01] // s1[4-7]
* s1-key-data=shared_key=DH_compute_key(peer_pub_key=c1-key-data)
* get c1s1-joined by specified schema
* s1-digest-data = HMACsha256(c1s1-joined, FMSKey, 36)
* copy s1-digest-data and s1-key-data to s1.
*/
virtual
int
s1_create
(
c1s1
*
c1
);
/**
* server: validate the parsed s1 schema
*/
virtual
int
s1_validate_digest
(
bool
&
is_valid
);
private
:
virtual
int
calc_s1_digest
(
char
*&
digest
);
virtual
int
calc_c1_digest
(
char
*&
digest
);
virtual
void
destroy_blocks
();
};
/**
...
...
请
注册
或
登录
后发表评论