SFTP 集成
SFTP(安全文件传输协议)是 QI CTVM 提供基金报告下载的渠道。各报告模型、每个文件的逐列布局以及可下载的示例,请参阅 DTVM 报告文档。
集成时,建议使用实现该协议的库和客户端,例如 Python 的 paramiko、命令行的 sftp,或任何标准 SFTP 客户端。
如需申请访问权限,请联系 integracao.dtvm@qitech.com.br。权限先在同质化环境(Sandbox)开放,随后在生产环境开放。
认证方式
访问认证使用 SSH 公钥,不使用密码。您生成密钥对,自行保管私钥,只需将公钥发送给我们,我们会将其登记到您的 SFTP 用户下。
| 提供方 | 提供内容 |
|---|---|
| 您 | 公钥(.pub 文件),OpenSSH 格式 |
| QI CTVM | HOSTNAME、PORT(22)和 USERNAME,以及主机指纹 |
QI Tech 的任何团队都不会索要您的私钥。如果有人索要——无论通过邮件、工单还是其他任何渠道——那都不是我们。第 3 步中的 1Password 共享仅用于公钥(sftp_qitech.pub)。
如果私钥已经发送给他人或作为附件上传过,请视其为已泄露:请重新生成密钥对,并将新的公钥发送给我们。
1. 生成密钥对
请生成专用于 SFTP 的密钥对。不要重用签发 JWT 令牌的密钥:它们是不同系统的凭证,生命周期不同——轮换其中一个就会被迫轮换另一个,而任何一侧泄露都会同时影响两者。
请将 company-name 替换为贵公司的名称,例如 sftp-acme。该文本仅是密钥中的注释,用于帮助我们识别该密钥。
- Linux / macOS
- Windows (PowerShell)
- Windows (cmd)
- Windows (WSL)
mkdir -p ~/.ssh && chmod 700 ~/.ssh
ssh-keygen -t ed25519 -C "sftp-company-name" -f ~/.ssh/sftp_qitech
New-Item -ItemType Directory -Force "$env:USERPROFILE\.ssh" | Out-Null
ssh-keygen -t ed25519 -C "sftp-company-name" -f "$env:USERPROFILE\.ssh\sftp_qitech"
if not exist "%USERPROFILE%\.ssh" mkdir "%USERPROFILE%\.ssh"
ssh-keygen -t ed25519 -C "sftp-company-name" -f "%USERPROFILE%\.ssh\sftp_qitech"
mkdir -p ~/.ssh && chmod 700 ~/.ssh
ssh-keygen -t ed25519 -C "sftp-company-name" -f ~/.ssh/sftp_qitech
在 WSL 中请使用 Linux 路径(~/.ssh)。密钥保存在 WSL 的文件系统中,而不是 Windows 的用户目录中。
每个标签页都按对应程序能识别的写法给出文件夹路径,因此这些命令不能互换使用。如果把某个标签页的命令放到另一个程序中运行,会出现 No such file or directory,并且不会生成任何密钥——这时只需回到正确的标签页重新复制命令即可。
在 Windows 上,如果不确定该用哪一个,请使用 PowerShell:它是 Windows 终端默认打开的程序。
该命令会询问口令(passphrase),并生成两个文件:
| 文件 | 说明 |
|---|---|
sftp_qitech | 私钥。 切勿发送,切勿共享。 |
sftp_qitech.pub | 公钥。 这是您需要发送给我们的文件。 |
关于口令:
- 自动化集成(由您的服务下载报告):留空即可(在两次提示时直接按 Enter),并在存放私钥的位置对其加以保护,例如访问受限的密钥管理服务。如果口令必须在运行时对进程可用,它并不会带来实质性的保护。
- 由人工使用:请设置口令。
ssh-keygen 生成的私钥权限默认仅限当前用户。如果您将该文件复制到另一台机器,请恢复其权限——SSH 客户端会拒绝其他用户可读的私钥:
chmod 600 ~/.ssh/sftp_qitech
2. 检查公钥格式
.pub 文件的内容是单独一行,以密钥类型开头,以注释结尾:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE1wA3uBEFYG+Yi7zIw7/YUJJ4fBB0MUZsvUVaqyyv6M sftp-acme
发送给我们之前,请先检查该文件:
ssh-keygen -lf ~/.ssh/sftp_qitech.pub
预期输出为密钥的指纹,格式形如 256 SHA256:... sftp-acme (ED25519)。如果命令返回 is not a public key file,说明文件已损坏,或者它不是 OpenSSH 公钥。
如果您的密钥是 PEM/X.509 格式
以 -----BEGIN PUBLIC KEY----- 开头的密钥属于 PEM/X.509 格式,即 OpenSSL 的标准格式。该格式无法登记到 SFTP:服务器要求单行的 OpenSSH 格式。
如果该密钥已经专用于 SFTP,您无需重新生成,只需转换格式:
-
您仍有对应的私钥。 适用于任意类型的密钥:
ssh-keygen -y -f 私钥路径 -
您只有 PEM 格式的公钥。 适用于 RSA 密钥:
ssh-keygen -i -m PKCS8 -f 公钥路径.pem
两个命令都会将 OpenSSH 格式的密钥输出到标准输出。转换不会保留原有注释;如有需要,可在行尾追加 sftp-company-name。
3. 发送公钥
请通过 1Password 发送公钥,并将该条目共享给集成团队。这是我们接收密钥的渠道:它能完整保留您生成的内容,并使发送来源可被验证——任何能够在传输过程中替换您公钥的人,都将获得对您 SFTP 目录的访问权限。
- 在 1Password 中创建一个条目,并将
sftp_qitech.pub文件的内容以纯文本形式粘贴进去,保持单独一行,不要换行。 - 附上密钥的指纹——即上一步
ssh-keygen -lf的输出。我们会将其与收到的密钥指纹进行比对,确认密钥在传输过程中未被篡改。 - 将该条目共享给集成团队,并通过 integracao.dtvm@qitech.com.br 告知我们已完成共享。
.docx 或 .pdf 附件发送密钥这些程序的自动格式化会替换字符(把 + 替换为破折号,把直引号替换为弯引号)并插入换行。任何这类改动都会使密钥失效,而错误只会在连接时才暴露出来。
公钥登记完成后,我们会确认权限开放,并向您提供 HOSTNAME、USERNAME 以及主机指纹。
4. 连接 SFTP
首次连接时请核对主机密钥
首次连接时,客户端会询问您是否信任该服务器。请勿不加核对就接受:将显示的指纹与集成团队提供的指纹进行比对。正是这一比对,才能防止其他服务器冒充我们的服务器。
ssh-keyscan -t ed25519 <hostname> > qitech_host_key
ssh-keygen -lf qitech_host_key # 与 QI CTVM 提供的指纹进行比对
cat qitech_host_key >> ~/.ssh/known_hosts
核对完成后,known_hosts 即成为客户端的比对依据,出现不同主机密钥的连接会被自动拒绝。
连接凭证
| 凭证 | 来源 |
|---|---|
HOSTNAME | 服务器地址,由 QI CTVM 提供 |
PORT | 22 |
USERNAME | 用户名,由 QI CTVM 提供 |
| 私钥 | 您自己生成的 sftp_qitech |
这些凭证可直接访问贵方基金的报告,不得与他人共享。
代码示例
- Python
import paramiko
HOSTNAME = "sftp.example.com" # 由 QI CTVM 提供
PORT = 22
USERNAME = "username" # 由 QI CTVM 提供
PRIVATE_KEY = "/path/to/sftp_qitech" # 您自己生成的私钥
KNOWN_HOSTS = "/path/to/known_hosts" # 其中已包含核对过的 QI CTVM 主机密钥
client = paramiko.SSHClient()
client.load_host_keys(KNOWN_HOSTS)
# 如果主机密钥与预期不符,则拒绝连接。
# 请勿使用 AutoAddPolicy:它会不加验证地接受任何服务器。
client.set_missing_host_key_policy(paramiko.RejectPolicy())
client.connect(
hostname=HOSTNAME,
port=PORT,
username=USERNAME,
key_filename=PRIVATE_KEY, # paramiko 会根据文件识别密钥类型
look_for_keys=False,
allow_agent=False,
timeout=30,
)
try:
with client.open_sftp() as sftp:
# 列出可用文件
for name in sftp.listdir("/"):
print(name)
# 下载文件
sftp.get("remote/path/file.csv", "local/path/file.csv")
finally:
client.close()
5. 下载文件
文件名由基金的简称、报告模型以及 YYYY-MM-DD 格式的参考日期组成:
example_name_assets_wallet_composition_2026-07-29.csv
各报告模型、每个文件的逐列布局以及可下载的示例,请参阅 DTVM 报告文档。
所提供的 SFTP 服务仅供下载文件使用;不允许进行上传。
密钥的轮换与吊销
如需更换密钥,请重新生成密钥对,并按第 1 至第 3 步通过 1Password 将新的公钥发送给我们。我们会登记新密钥,并在移除旧密钥后通知您,使切换过程不产生服务中断窗口。
如果怀疑私钥已泄露,请通过同一联系方式通知集成团队:我们会先立即吊销旧密钥的访问权限,再登记新密钥。