Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
Docs
提交
a647197c
D
Docs
项目概览
OpenHarmony
/
Docs
大约 1 年 前同步成功
通知
159
Star
292
Fork
28
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
Docs
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
a647197c
编写于
6月 01, 2023
作者:
O
openharmony_ci
提交者:
Gitee
6月 01, 2023
浏览文件
操作
浏览文件
下载
差异文件
!19015 【开发自提单】同步主干,修改Crypto_framework guideline文档,优化Hmac和Md示例代码。
Merge pull request !19015 from 胡啸天/OpenHarmony-4.0-Beta1
上级
21221e37
bd3a7ed6
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
166 addition
and
181 deletion
+166
-181
zh-cn/application-dev/security/cryptoFramework-guidelines.md
zh-cn/application-dev/security/cryptoFramework-guidelines.md
+166
-181
未找到文件。
zh-cn/application-dev/security/cryptoFramework-guidelines.md
浏览文件 @
a647197c
...
...
@@ -1130,83 +1130,70 @@ function signLongMessagePromise() {
```
javascript
import
cryptoFramework
from
"
@ohos.security.cryptoFramework
"
//
turn string into uint8Arr
//
可理解的字符串转成字节流
function
stringToUint8Array
(
str
)
{
var
arr
=
[];
for
(
var
i
=
0
,
j
=
str
.
length
;
i
<
j
;
++
i
)
{
arr
.
push
(
str
.
charCodeAt
(
i
));
}
var
tmpUint8Array
=
new
Uint8Array
(
arr
);
return
tmpUint8Array
;
}
// generate dataBlob with given length
function
GenDataBlob
(
dataBlobLen
)
{
var
dataBlob
;
if
(
dataBlobLen
==
12
)
{
dataBlob
=
{
data
:
stringToUint8Array
(
"
my test data
"
)};
}
else
{
console
.
error
(
"
GenDataBlob: dataBlobLen is invalid
"
);
dataBlob
=
{
data
:
stringToUint8Array
(
"
my test data
"
)};
let
arr
=
[];
for
(
let
i
=
0
,
j
=
str
.
length
;
i
<
j
;
++
i
)
{
arr
.
push
(
str
.
charCodeAt
(
i
));
}
return
dataBlob
;
return
new
Uint8Array
(
arr
)
;
}
// md with promise async
function
doMdByPromise
(
algName
)
{
var
md
;
// 以Promise方式完成摘要
function
doMdByPromise
()
{
let
mdAlgName
=
"
SHA256
"
;
// 摘要算法名
let
message
=
"
mdTestMessgae
"
;
// 待摘要数据
let
md
;
let
mdOutput
;
try
{
md
=
cryptoFramework
.
createMd
(
a
lgName
);
md
=
cryptoFramework
.
createMd
(
mdA
lgName
);
}
catch
(
error
)
{
console
.
error
(
"
[Promise]: error code:
"
+
error
.
code
+
"
, message is:
"
+
error
.
message
);
return
;
}
console
.
error
(
"
[Promise]: Md algName is:
"
+
md
.
algName
);
//
初次update
var
promiseMdUpdate
=
md
.
update
(
GenDataBlob
(
12
)
);
console
.
info
(
"
[Promise]: Md algName is:
"
+
md
.
algName
);
//
数据量较少时,可以只做一次update,将数据全部传入,接口未对入参长度做限制
let
promiseMdUpdate
=
md
.
update
({
data
:
stringToUint8Array
(
message
)
}
);
promiseMdUpdate
.
then
(()
=>
{
// 可根据情况进行多次update
promiseMdUpdate
=
md
.
update
(
GenDataBlob
(
12
));
return
promiseMdUpdate
;
}).
then
(
mdOutput
=>
{
var
PromiseMdDigest
=
md
.
digest
();
// 通过digest,返回摘要结果
let
PromiseMdDigest
=
md
.
digest
();
return
PromiseMdDigest
;
}).
then
(
mdOutput
=>
{
console
.
error
(
"
[Promise]: MD result:
"
+
mdOutput
.
data
);
var
mdLen
=
md
.
getMdLength
();
console
.
error
(
"
[Promise]: MD len:
"
+
mdLen
);
}).
then
(
digestOutput
=>
{
mdOutput
=
digestOutput
;
console
.
info
(
"
[Promise]: MD result:
"
+
mdOutput
.
data
);
let
mdLen
=
md
.
getMdLength
();
console
.
info
(
"
[Promise]: MD len:
"
+
mdLen
);
}).
catch
(
error
=>
{
console
.
error
(
"
[Promise]: error:
"
+
error
.
message
);
});
}
// md with callback async
function
doMdByCallback
(
algName
)
{
var
md
;
// 以Callback方式完成摘要
function
doMdByCallback
()
{
let
mdAlgName
=
"
SHA256
"
;
// 摘要算法名
let
message
=
"
mdTestMessgae
"
;
// 待摘要数据
let
md
;
let
mdOutput
;
try
{
md
=
cryptoFramework
.
createMd
(
a
lgName
);
md
=
cryptoFramework
.
createMd
(
mdA
lgName
);
}
catch
(
error
)
{
console
.
error
(
"
[Callback]: error code:
"
+
error
.
code
+
"
, message is:
"
+
error
.
message
);
}
console
.
error
(
"
[Callback]: Md algName is:
"
+
md
.
algName
);
//
初次update
md
.
update
(
GenDataBlob
(
12
)
,
(
err
,)
=>
{
console
.
info
(
"
[Callback]: Md algName is:
"
+
md
.
algName
);
//
数据量较少时,可以只做一次update,将数据全部传入,接口未对入参长度做限制
md
.
update
(
{
data
:
stringToUint8Array
(
message
)
}
,
(
err
,)
=>
{
if
(
err
)
{
console
.
error
(
"
[Callback]: err:
"
+
err
.
code
);
}
// 可根据情况进行多次update
md
.
update
(
GenDataBlob
(
12
),
(
err1
,)
=>
{
md
.
digest
((
err1
,
digestOutput
)
=>
{
if
(
err1
)
{
console
.
error
(
"
[Callback]: err:
"
+
err1
.
code
);
}
else
{
mdOutput
=
digestOutput
;
console
.
info
(
"
[Callback]: MD result:
"
+
mdOutput
.
data
);
let
mdLen
=
md
.
getMdLength
();
console
.
info
(
"
[Callback]: MD len:
"
+
mdLen
);
}
md
.
digest
((
err2
,
mdOutput
)
=>
{
if
(
err2
)
{
console
.
error
(
"
[Callback]: err:
"
+
err2
.
code
);
}
else
{
console
.
error
(
"
[Callback]: MD result:
"
+
mdOutput
.
data
);
var
mdLen
=
md
.
getMdLength
();
console
.
error
(
"
[Callback]: MD len:
"
+
mdLen
);
}
});
});
});
}
...
...
@@ -1215,54 +1202,56 @@ function doMdByCallback(algName) {
```
javascript
import
cryptoFramework
from
"
@ohos.security.cryptoFramework
"
async
function
updateData
(
index
,
obj
,
data
)
{
console
.
error
(
"
update
"
+
(
index
+
1
)
+
"
MB data...
"
);
return
obj
.
update
(
data
);
}
// 可理解的字符串转成字节流
function
stringToUint8Array
(
str
)
{
var
arr
=
[];
for
(
var
i
=
0
,
j
=
str
.
length
;
i
<
j
;
++
i
)
{
let
arr
=
[];
for
(
let
i
=
0
,
j
=
str
.
length
;
i
<
j
;
++
i
)
{
arr
.
push
(
str
.
charCodeAt
(
i
));
}
var
tmpUint8Array
=
new
Uint8Array
(
arr
);
return
tmpUint8Array
;
return
new
Uint8Array
(
arr
);
}
function
GenDataBlob
(
dataBlobLen
)
{
var
dataBlob
;
if
(
dataBlobLen
==
12
)
{
dataBlob
=
{
data
:
stringToUint8Array
(
"
my test data
"
)};
}
else
{
console
.
error
(
"
GenDataBlob: dataBlobLen is invalid
"
);
dataBlob
=
{
data
:
stringToUint8Array
(
"
my test data
"
)};
}
return
dataBlob
;
}
function
LoopMdPromise
(
algName
,
loopSize
)
{
var
md
;
// 使用Promise方式,完成分段摘要
async
function
doLoopMdPromise
()
{
let
mdAlgName
=
"
SHA256
"
;
// 摘要算法名
let
md
;
let
mdOutput
;
try
{
md
=
cryptoFramework
.
createMd
(
a
lgName
);
md
=
cryptoFramework
.
createMd
(
mdA
lgName
);
}
catch
(
error
)
{
console
.
error
(
"
[Promise]: error code:
"
+
error
.
code
+
"
, message is:
"
+
error
.
message
);
return
;
}
console
.
error
(
"
[Promise]: Md algName is:
"
+
md
.
algName
);
var
promiseMdUpdate
=
md
.
update
(
GenDataBlob
(
12
));
promiseMdUpdate
.
then
(()
=>
{
var
PromiseMdDigest
=
md
.
digest
();
return
PromiseMdDigest
;
}).
then
(
async
()
=>
{
for
(
var
i
=
0
;
i
<
loopSize
;
i
++
)
{
await
updateData
(
i
,
md
,
GenDataBlob
(
12
));
console
.
info
(
"
[Promise]: Md algName is:
"
+
md
.
algName
);
let
messageText
=
"
aaaaa.....bbbbb.....ccccc.....ddddd.....eee
"
;
// 假设信息总共43字节
let
messageArr
=
[];
let
updateLength
=
20
;
// 假设每20字节分段update一次,实际并无要求
for
(
let
i
=
0
;
i
<=
messageText
.
length
;
i
++
)
{
if
((
i
%
updateLength
==
0
||
i
==
messageText
.
length
)
&&
messageArr
.
length
!=
0
)
{
let
message
=
new
Uint8Array
(
messageArr
);
let
messageBlob
=
{
data
:
message
};
// 使用await处理for循环里的update
try
{
await
md
.
update
(
messageBlob
);
// 分段update
}
catch
(
error
)
{
console
.
error
(
"
await update error code:
"
+
error
.
code
+
"
, message is:
"
+
error
.
message
);
return
;
}
messageArr
=
[];
}
var
PromiseMdDigest
=
md
.
digest
();
return
PromiseMdDigest
;
}).
then
(
mdOutput
=>
{
console
.
error
(
"
[Promise]: MD result:
"
+
mdOutput
.
data
);
var
mdLen
=
md
.
getMdLength
();
console
.
error
(
"
[Promise]: MD len:
"
+
mdLen
);
// 按分割长度,填充messageArr
if
(
i
<
messageText
.
length
)
{
messageArr
.
push
(
messageText
.
charCodeAt
(
i
));
}
}
let
PromiseMdDigest
=
md
.
digest
();
PromiseMdDigest
.
then
(
digestOutput
=>
{
mdOutput
=
digestOutput
;
console
.
info
(
"
[Promise]: MD result:
"
+
mdOutput
.
data
);
let
mdLen
=
md
.
getMdLength
();
console
.
info
(
"
[Promise]: MD len:
"
+
mdLen
);
}).
catch
(
error
=>
{
console
.
error
(
"
[Promise]: error:
"
+
error
.
message
);
});
...
...
@@ -1374,77 +1363,72 @@ Mac(message authentication code)可以对消息进行完整性校验,通过使
```
javascript
import
cryptoFramework
from
"
@ohos.security.cryptoFramework
"
//
turn string into uint8Arr
//
可理解的字符串转成字节流
function
stringToUint8Array
(
str
)
{
var
arr
=
[];
for
(
var
i
=
0
,
j
=
str
.
length
;
i
<
j
;
++
i
)
{
arr
.
push
(
str
.
charCodeAt
(
i
));
}
var
tmpUint8Array
=
new
Uint8Array
(
arr
);
return
tmpUint8Array
;
}
// generate blob with this func
function
GenDataBlob
(
dataBlobLen
)
{
var
dataBlob
;
if
(
dataBlobLen
==
12
)
{
dataBlob
=
{
data
:
stringToUint8Array
(
"
my test data
"
)};
}
else
{
console
.
error
(
"
GenDataBlob: dataBlobLen is invalid
"
);
dataBlob
=
{
data
:
stringToUint8Array
(
"
my test data
"
)};
let
arr
=
[];
for
(
let
i
=
0
,
j
=
str
.
length
;
i
<
j
;
++
i
)
{
arr
.
push
(
str
.
charCodeAt
(
i
));
}
return
dataBlob
;
return
new
Uint8Array
(
arr
)
;
}
function
doHmacByPromise
(
algName
)
{
var
mac
;
// 以Promise方式完成HMAC
function
doHmacByPromise
()
{
let
macAlgName
=
"
SHA256
"
;
// 摘要算法名
let
message
=
"
hmacTestMessgae
"
;
// 待hmac数据
let
macOutput
;
let
mac
;
try
{
mac
=
cryptoFramework
.
createMac
(
a
lgName
);
mac
=
cryptoFramework
.
createMac
(
macA
lgName
);
}
catch
(
error
)
{
console
.
error
(
"
[Promise]: error code:
"
+
error
.
code
+
"
, message is:
"
+
error
.
message
);
}
console
.
error
(
"
[Promise]: Mac algName is:
"
+
mac
.
algName
);
var
KeyBlob
=
{
console
.
info
(
"
[Promise]: Mac algName is:
"
+
mac
.
algName
);
let
KeyBlob
=
{
// 128位密钥
data
:
stringToUint8Array
(
"
12345678abcdefgh
"
)
}
var
symKeyGenerator
=
cryptoFramework
.
createSymKeyGenerator
(
"
AES128
"
);
var
promiseConvertKey
=
symKeyGenerator
.
convertKey
(
KeyBlob
);
let
symKeyGenerator
=
cryptoFramework
.
createSymKeyGenerator
(
"
AES128
"
);
// 将二进制密钥转换为算法库密钥
let
promiseConvertKey
=
symKeyGenerator
.
convertKey
(
KeyBlob
);
promiseConvertKey
.
then
(
symKey
=>
{
var
promiseMacInit
=
mac
.
init
(
symKey
);
let
promiseMacInit
=
mac
.
init
(
symKey
);
return
promiseMacInit
;
}).
then
(()
=>
{
// 初次update
var
promiseMacUpdate
=
mac
.
update
(
GenDataBlob
(
12
));
return
promiseMacUpdate
;
}).
then
(()
=>
{
// 可根据情况进行多次update
var
promiseMacUpdate
=
mac
.
update
(
GenDataBlob
(
12
));
// 数据量较少时,可以只做一次update,将数据全部传入,接口未对入参长度做限制
let
promiseMacUpdate
=
mac
.
update
({
data
:
stringToUint8Array
(
message
)
});
return
promiseMacUpdate
;
}).
then
(()
=>
{
var
PromiseMacDoFinal
=
mac
.
doFinal
();
let
PromiseMacDoFinal
=
mac
.
doFinal
();
return
PromiseMacDoFinal
;
}).
then
(
macOutput
=>
{
console
.
error
(
"
[Promise]: HMAC result:
"
+
macOutput
.
data
);
var
macLen
=
mac
.
getMacLength
();
console
.
error
(
"
[Promise]: MAC len:
"
+
macLen
);
}).
then
(
output
=>
{
macOutput
=
output
;
console
.
info
(
"
[Promise]: HMAC result:
"
+
macOutput
.
data
);
let
macLen
=
mac
.
getMacLength
();
console
.
info
(
"
[Promise]: MAC len:
"
+
macLen
);
}).
catch
(
error
=>
{
console
.
error
(
"
[Promise]: error:
"
+
error
.
message
);
});
}
// process by callback
function
doHmacByCallback
(
algName
)
{
var
mac
;
// 以Callback方式完成HMAC
function
doHmacByCallback
()
{
let
macAlgName
=
"
SHA256
"
;
// 摘要算法名
let
message
=
"
hmacTestMessgae
"
;
// 待hmac数据
let
macOutput
;
let
mac
;
try
{
mac
=
cryptoFramework
.
createMac
(
a
lgName
);
mac
=
cryptoFramework
.
createMac
(
macA
lgName
);
}
catch
(
error
)
{
AlertDialog
.
show
({
message
:
"
[Callback]: error code:
"
+
error
.
code
+
"
, message is:
"
+
error
.
message
});
console
.
error
(
"
[Callback]: error code:
"
+
error
.
code
+
"
, message is:
"
+
error
.
message
);
}
var
KeyBlob
=
{
console
.
info
(
"
[Promise]: Mac algName is:
"
+
mac
.
algName
);
let
KeyBlob
=
{
// 128位密钥
data
:
stringToUint8Array
(
"
12345678abcdefgh
"
)
}
var
symKeyGenerator
=
cryptoFramework
.
createSymKeyGenerator
(
"
AES128
"
);
let
symKeyGenerator
=
cryptoFramework
.
createSymKeyGenerator
(
"
AES128
"
);
// 将二进制密钥转换为算法库密钥
symKeyGenerator
.
convertKey
(
KeyBlob
,
(
err
,
symKey
)
=>
{
if
(
err
)
{
console
.
error
(
"
[Callback]: err:
"
+
err
.
code
);
...
...
@@ -1453,25 +1437,20 @@ function doHmacByCallback(algName) {
if
(
err1
)
{
console
.
error
(
"
[Callback]: err:
"
+
err1
.
code
);
}
//
初次update
mac
.
update
(
GenDataBlob
(
12
)
,
(
err2
,
)
=>
{
//
数据量较少时,可以只做一次update,将数据全部传入,接口未对入参长度做限制
mac
.
update
(
{
data
:
stringToUint8Array
(
message
)
}
,
(
err2
,
)
=>
{
if
(
err2
)
{
console
.
error
(
"
[Callback]: err:
"
+
err2
.
code
);
}
// 可根据情况进行多次update
mac
.
update
(
GenDataBlob
(
12
),
(
err3
,
)
=>
{
mac
.
doFinal
((
err3
,
output
)
=>
{
if
(
err3
)
{
console
.
error
(
"
[Callback]: err:
"
+
err3
.
code
);
}
else
{
macOutput
=
output
;
console
.
info
(
"
[Callback]: HMAC result:
"
+
macOutput
.
data
);
let
macLen
=
mac
.
getMacLength
();
console
.
info
(
"
[Callback]: MAC len:
"
+
macLen
);
}
mac
.
doFinal
((
err4
,
macOutput
)
=>
{
if
(
err4
)
{
console
.
error
(
"
[Callback]: err:
"
+
err4
.
code
);
}
else
{
console
.
error
(
"
[Callback]: HMAC result:
"
+
macOutput
.
data
);
var
macLen
=
mac
.
getMacLength
();
console
.
error
(
"
[Callback]: MAC len:
"
+
macLen
);
}
});
});
});
});
...
...
@@ -1482,61 +1461,67 @@ function doHmacByCallback(algName) {
```
javascript
import
cryptoFramework
from
"
@ohos.security.cryptoFramework
"
async
function
updateData
(
index
,
obj
,
data
)
{
console
.
error
(
"
update
"
+
(
index
+
1
)
+
"
MB data...
"
);
return
obj
.
update
(
data
);
}
function
stringToUint8Array
(
str
)
{
var
arr
=
[];
for
(
var
i
=
0
,
j
=
str
.
length
;
i
<
j
;
++
i
)
{
let
arr
=
[];
for
(
let
i
=
0
,
j
=
str
.
length
;
i
<
j
;
++
i
)
{
arr
.
push
(
str
.
charCodeAt
(
i
));
}
var
tmpUint8Array
=
new
Uint8Array
(
arr
);
return
tmpUint8Array
;
}
function
GenDataBlob
(
dataBlobLen
)
{
var
dataBlob
;
if
(
dataBlobLen
==
12
)
{
dataBlob
=
{
data
:
stringToUint8Array
(
"
my test data
"
)};
}
else
{
console
.
error
(
"
GenDataBlob: dataBlobLen is invalid
"
);
dataBlob
=
{
data
:
stringToUint8Array
(
"
my test data
"
)};
}
return
dataBlob
;
return
new
Uint8Array
(
arr
);
}
function
LoopHmacPromise
(
algName
,
loopSize
)
{
var
mac
;
function
doLoopHmacPromise
()
{
let
macAlgName
=
"
SHA256
"
;
// 摘要算法名
let
macOutput
;
let
mac
;
try
{
mac
=
cryptoFramework
.
createMac
(
a
lgName
);
mac
=
cryptoFramework
.
createMac
(
macA
lgName
);
}
catch
(
error
)
{
console
.
error
(
"
[Promise]: error code:
"
+
error
.
code
+
"
, message is:
"
+
error
.
message
);
return
;
}
console
.
error
(
"
[Promise]: Mac algName is:
"
+
mac
.
algName
);
var
KeyBlob
=
{
console
.
info
(
"
[Promise]: Mac algName is:
"
+
mac
.
algName
);
let
KeyBlob
=
{
// 128位密钥
data
:
stringToUint8Array
(
"
12345678abcdefgh
"
)
}
var
symKeyGenerator
=
cryptoFramework
.
createSymKeyGenerator
(
"
AES128
"
);
var
promiseConvertKey
=
symKeyGenerator
.
convertKey
(
KeyBlob
);
let
messageText
=
"
aaaaa.....bbbbb.....ccccc.....ddddd.....eee
"
;
// 假设信息总共43字节
let
updateLength
=
20
;
// 假设每20字节分段update一次,实际并无要求
let
symKeyGenerator
=
cryptoFramework
.
createSymKeyGenerator
(
"
AES128
"
);
// 将二进制密钥转换为算法库密钥
let
promiseConvertKey
=
symKeyGenerator
.
convertKey
(
KeyBlob
);
promiseConvertKey
.
then
(
symKey
=>
{
var
promiseMacInit
=
mac
.
init
(
symKey
);
let
promiseMacInit
=
mac
.
init
(
symKey
);
return
promiseMacInit
;
}).
then
(
async
()
=>
{
for
(
var
i
=
0
;
i
<
loopSize
;
i
++
)
{
await
updateData
(
i
,
mac
,
GenDataBlob
(
12
));
let
promiseMacUpdate
;
let
messageArr
=
[];
for
(
let
i
=
0
;
i
<=
messageText
.
length
;
i
++
)
{
if
((
i
%
updateLength
==
0
||
i
==
messageText
.
length
)
&&
messageArr
.
length
!=
0
)
{
let
message
=
new
Uint8Array
(
messageArr
);
let
messageBlob
=
{
data
:
message
};
// 使用await处理for循环里的update
try
{
promiseMacUpdate
=
await
mac
.
update
(
messageBlob
);
// 分段update
}
catch
(
error
)
{
console
.
error
(
"
await update error code:
"
+
error
.
code
+
"
, message is:
"
+
error
.
message
);
return
;
}
messageArr
=
[];
}
// 按分割长度,填充messageArr
if
(
i
<
messageText
.
length
)
{
messageArr
.
push
(
messageText
.
charCodeAt
(
i
));
}
}
var
promiseMacUpdate
=
mac
.
update
(
GenDataBlob
(
12
));
return
promiseMacUpdate
;
}).
then
(()
=>
{
var
PromiseMacDoFinal
=
mac
.
doFinal
();
let
PromiseMacDoFinal
=
mac
.
doFinal
();
return
PromiseMacDoFinal
;
}).
then
(
macOutput
=>
{
console
.
error
(
"
[Promise]: HMAC result:
"
+
macOutput
.
data
);
var
macLen
=
mac
.
getMacLength
();
console
.
error
(
"
[Promise]: MAC len:
"
+
macLen
);
}).
then
(
output
=>
{
macOutput
=
output
;
console
.
log
(
"
[Promise]: HMAC result:
"
+
macOutput
.
data
);
let
macLen
=
mac
.
getMacLength
();
console
.
log
(
"
[Promise]: MAC len:
"
+
macLen
);
}).
catch
(
error
=>
{
console
.
error
(
"
[Promise]: error:
"
+
error
.
message
);
});
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录