BankAPI

金融机构之间的安全分布式信息传递。「Secure Distributed Messaging Between Financial Institutions」

  • Owner: trustly/bankapi
  • Platform: Linux, Mac, Windows
  • License:: MIT License
  • Category::
  • Topic:
  • Like:
    0
      Compare:

Github stars Tracking Chart

BankAPI

它是什么?

BankAPI 是一个安全的分布式消息系统,用于在银行和其他类型的金融机构之间发送文件/消息。

有一个可以现成使用的协议参考实现,它是生产级质量,不仅用于测试和演示,尽管它也满足这两个作用。

BankAPI 协议依赖于 OpenPGP(RFC 4880)+ SHA512+HTTPS。就是这样,没有其他的东西了。

BankAPI 只是一个传输协议,并没有假设银行要传输什么样的信息或文件类型。

密钥交换

layout

协议设计

layout

该协议对用于生成 OpenPGP 消息的算法的细节和选择施加了某些限制。这里使用的术语符合 RFC2119 中规定的术语。具体到 OpenPGP 的细节在 RFC4880 中有所记载。

  1. 所有 OpenPGP 消息必须是对称加密的消息,其中会话密钥是公钥加密的。会话密钥包必须包含用于加密消息的密钥 ID。所有消息都必须包含一个签名包。实施者可以选择生成单通签名。
  2. 所有各方必须为他们的 RSA 密钥使用至少 2048 位的密钥长度。实施方案应该接受 2048、3072 和 4096 比特的密钥大小。建议使用 4096 位密钥。不得使用 DSA 和 Elgamal。
  3. 密码算法必须是 AES128、AES192 和 AES256 中的一种。
  4. 如果 OpenPGP 消息是一个压缩的消息,压缩算法必须是 ZIP 或 ZLIB。
  5. OpenPGP 消息可以通过修改检测代码包进行完整性保护。
  6. OpenPGP 消息中的文字数据必须被标记为包含二进制数据。如果收到文本或 UTF-8 消息,实现者可以选择接受该消息。一个实施方案不得将任何规范的行结尾转换为其本地对应的行结尾。
  7. 签名包和(如果有的话)单通签名包必须包含用于签署消息的钥匙的钥匙 ID。实施方案应只使用单一的密钥来签署信息。用于签名的哈希算法必须是 SHA-512。
  8. ASCII Armor,包括 Armor Headers,必须是有效的 UTF-8。
  9. Armor 头的 "注释",必须被设置为消息类型。

系统设计

layout

该系统建立在 PostgreSQL 之上,使用其 pgcrypto contrib 模块。

信息使用 RSA 公钥加密法进行加密和签名。

每家银行都会生成一个 RSA 密钥对,包括一个公钥和一个秘钥。

公钥和 API URL 在银行之间进行交换。

交换公钥和 API URL 的任务最好通过 SWIFT 网络完成,在正常的 MT999 SWIFT FIN-message 中发送。这使银行能够信任公钥和 API URL 的有效性,因为 SWIFT 报文的来源是可以信任的。

亮点

  • RSA 加密
  • SHA512
  • json-rpc / https
  • Linux / PostgreSQL / Apache
  • 开放源码/MIT-license
  • 实时请求/响应
  • 即时交付接收
  • 在 PostgreSQL 中对文件进行本地归档

接口概述

为了发送信息,发送银行使用 Create_Message() 对信息进行加密和签名,并调用 Get_Message() 来获得信息的实际密码文本内容。然后通过调用接收银行的 Receive_Message() API 方法将密码文本传递给接收银行,接收银行提供的 API URL 可以访问。API 实现必须遵守 JSON-RPC 标准并接受 HTTPS POST。

Receive_Message() 函数返回一个交付收据,这是一个加密证明,证明发送方能够根据接收银行的公钥验证信息中包含的签名。这使得发送方可以确定信息已被发送并被接收方成功解密。

发送银行调用 Decode_Delivery_Receipt(),以发送收据为输入,验证其有效性。

数据库表和列

银行(Banks)

  • BankID:银行的唯一标识符,最好是 SWIFT BIC(PRIMARY KEY)
  • Protocol:API 程序,例如 "https"
  • Host:API 主机,互联网域名,例如 "bank.com"
  • Port:API 端口,互联网网络端口,例如 443
  • Path:API路径,例如"/api"
  • Datestamp : 添加到表中的日期/时间

文件(Files)

  • FileID : 纯文本的SHA512哈希值(PRIMARY KEY)
  • Plaintext : 文件的内容(UTF8)。
  • Datestamp:添加到表中的日期/时间

密钥(Keys)

  • MainKeyID : 签名密钥(主键)。
  • SubKeyID : 加密密钥
  • PublicKeyring : 包含公钥
  • SecretKeyring : 包含密钥(只为自己的银行设置,对其他银行为空)
  • BankID : 钥匙所属的银行 ID
  • Datestamp : 添加到表中的日期/时间
  • PrimaryKey : 每个银行 ID 只有一行设置为 "true",其他密钥仍然有效,但这个密钥在创建新信息时被使用。

信息(Messages)

  • MessageID : Cipherdata的SHA512哈希值(PRIMARY KEY)
  • FileID : 消息中发送的文件的哈希值
  • FromBankID : 发送信息的银行
  • ToBankID : 接收信息的银行
  • Cipherdata : 加密和签名的信息
  • DeliveryReceipt : 加密和签署的交货收据
  • Datestamp : 信息创建的日期/时间
  • Delivered : 信息被交付的日期/时间

数据库函数

Create_Message(Plaintext, FromBankID, ToBankID)

Create_Message() 将文件的明文上下文作为输入,并准备一个由 FromBankID 签名的加密信息,只能由 ToBankID 解密。如果消息已经存在,现有的数据将被重新使用。如果 FromBankID 的秘钥或 ToBankID 的公钥无法在数据库中找到,则返回错误。

返回值是该消息的 message ID。

Get_Message(MessageID)

给出一个 message ID 作为输入,Get_Message() 返回 ASCII 装甲 PGP 消息。然后,该数据可以通过 HTTPS 发布到 ToBank 的 Receive_Message API 方法。

Receive_Message(Ciphertext text)

Receive_Message() 对输入的信息进行解密并验证其签名。消息的详细信息被写入信息表,关于文件及其明文内容的信息被写入文件表。这个函数将引发一个错误,如果:

  1. 用于加密信息的公钥对应的秘钥没有出现在 Keys 表中。
  2. 用于签名信息的公钥对应的密匙不在 Keys 表中。
  3. 信息被破坏或签名无法被验证。

返回值是一个交付收据,然后应将其作为对 Receive_Message API 方法调用者的响应内容。

Decode_Delivery_Receipt(DeliveryReceipt text)

Decode_Delivery_Receipt() 对给定的收据进行解密和验证,其中涉及的密钥和明文应该与 Messages 中的一行相匹配。如果是这样,消息就被成功传递了,并且 Messages.DeliveryReceipt 和 Messages.Delivered 列被设置。

安装和构建 .deb 包进行安装

存储库包括为 bankapi 和所需的 pgcrypto 扩展(在 PostgreSQL 中)构建 debian/ubuntu 包的脚本,以便运行代码。

如果你运行的是与 9.3 版本不同的 PostgreSQL,那么请将下面的命令中的版本替换为合适的版本。如果您运行的是 Debian 中的默认版本,您可以省略软件包名称中的版本扩展。

  • sudo apt-get -y build-dep postgresql-9.3
  • sudo apt-get -y install postgresql-server-dev-9.3 postgresql-9.3 apache2 python-psycopg2 python-requests
  • make

这将产生两个 deb 文件,一个是 bankapi,一个是 pgcrypto 扩展。

bankapi-1.0.deb

包包含了发送消息的命令行工具(/usr/bin/bankapi),在 postgres 中创建 bankapi 所需的 SQL,并安装了一个 CGI 作为接收传入通信消息的端点。

该模块的安装会安装和激活 CGI 脚本。它将在 http://localhost/bankapi 。

安装并没有完成数据库的安装,而是将其作为一项手动任务。按照以下步骤进行默认数据库的安装。

  • cd /usr/share/bankapi
  • sudo -u postgres createdb bankapi
  • sudo -u postgres psql --dbname=bankapi --single-transaction --no-psqlrc --file=install.sql
  • 确保www-data用户可以连接到bankapi数据库,这可以通过在活动的pg_hba.conf文件中适当添加以下一行来完成: local bankapi www-data peer
  • 可以选择安装测试银行数据: sudo -u postgres psql --dbname=bankapi --single-transaction --no-psqlrc --file=testdata/index.sql

postgresql-pgcrypto-openpgp-9.3.deb

这是 pgcrypto PostgreSQL 扩展的一个扩展。这个扩展只安装了扩展的功能,所有通常在 pgcrypto 中的功能仍然可以从标准的 pgcrypto 扩展中访问。该扩展名为pgcrypto_openpgp。

(The first version translated by vz on 2021.09.25)


Main metrics

Overview
Name With Ownertrustly/bankapi
Primary LanguagePython
Program languageShell (Language Count: 2)
PlatformLinux, Mac, Windows
License:MIT License
所有者活动
Created At2014-08-04 13:28:29
Pushed At2014-11-01 14:56:53
Last Commit At2014-11-01 15:47:06
Release Count0
用户参与
Stargazers Count779
Watchers Count51
Fork Count64
Commits Count162
Has Issues Enabled
Issues Count2
Issue Open Count0
Pull Requests Count3
Pull Requests Open Count0
Pull Requests Close Count0
项目设置
Has Wiki Enabled
Is Archived
Is Fork
Is Locked
Is Mirror
Is Private

BankAPI

What is it?

BankAPI is a secure decentralized messaging system to send files/messages between banks and other types of financial institutions.

There is a reference implementation of the protocol which can be used off-the-shelf, which is production grade quality and is not only for testing and demonstration, although it fulfils those two roles as well.

The BankAPI protocol relies on OpenPGP (RFC 4880) + SHA512 + HTTPS. That's it, there is nothing more to it.

BankAPI is only a transmission protocol, and makes no assumptions of what kind of messages or file types banks will want to transfer.

Key exchange

layout

Protocol design

layout

The protocol imposes certain restrictions on the details and choices of
algorithms used for generating the OpenPGP messages. The terminology used here
conforms to the one specified in RFC2119.
The details specific to OpenPGP are documented in
RFC4880.

  1. All OpenPGP messages MUST be symmetrically encrypted messages, where the
    session key is public-key encrypted. The session key packet MUST
    contain the Key ID of the key used to encrypt the message. All messages
    MUST contain a signature packet. Implementations MAY choose to
    generate one-pass signatures.

  2. All parties MUST use a key length of at least 2048 bits for their RSA
    keys. Implementations SHOULD accept key sizes of 2048, 3072 and 4096
    bits. Using 4096-bit keys is RECOMMENDED. DSA and Elgamal MUST NOT
    be used.

  3. The cipher algorithm MUST be one of AES128, AES192 and AES256.

  4. If the OpenPGP message is a compressed message, the compression algorithm
    MUST be ZIP or ZLIB.

  5. The OpenPGP message MAY be integrity protected via the Modification
    Detection Code packet
    .

  6. The literal data inside the OpenPGP message MUST be marked to contain
    binary data. If a text or UTF-8 message is received, an implementation
    MAY choose to accept the message. An implementation MUST NOT
    convert any canonical line endings to their local counterpart.

  7. The signature packet and (if present) the one-pass signature packet MUST
    contain the Key ID of the key used to sign the message. Implementations
    SHOULD only sign a message using a single key. The hash algorithm used
    for signatures MUST be SHA-512.

  8. The ASCII Armor, including Armor Headers, MUST be valid UTF-8.

  9. The Armor Header "Comment", MUST be set to the message type.

System design

layout

The system is built on top of PostgreSQL and uses its pgcrypto contrib module.

Messages are encrypted and signed using RSA public-key cryptography.

Each bank generates a RSA key-pair consisting of a public and a secret key.

The public keys and API URLs are exchanged between the banks.

The task of exchanging public keys and API URLs is preferrably done over the
SWIFT network, by sending them in a normal MT999 SWIFT FIN-message. This
allows banks to trust the validity of the public key and API URL, as the origin
of SWIFT messages can be trusted.

Highlights

  • RSA-encryption
  • SHA512
  • JSON-RPC / HTTPS
  • Linux / PostgreSQL / Apache
  • Open source / MIT-license
  • Real-time request/response
  • Instant delivery receipt
  • Local archiving of files in PostgreSQL

Overview of the interface

To send a message, the sending bank encrypts and signs a message using
Create_Message(), and calls Get_Message() to get the actual ciphertext
content of the message. The ciphertext is then delivered to the receiving bank
by calling its Receive_Message() API method, accessible at the API URL
provided by the receiving bank. The API implementation must adhere to the
JSON-RPC standard and accept HTTPS POST.

The Receive_Message() function returns a delivery receipt, which is a
cryptographic proof of the fact that the sender was able to verify the
signature contained within the message against the receiving bank's public key.
This allows the sender to be certain that the message was delivered and
decrypted successfully by the recipient.

The sending bank calls Decode_Delivery_Receipt() with the delivery receipt
as input to verify its validity.

Database tables and columns

Banks

  • BankID : Unique identifier for the bank, preferrably the SWIFT BIC (PRIMARY KEY)
  • Protocol : API procotol, example "https"
  • Host : API host, Internet domain name, example "bank.com"
  • Port : API port, Internet network port, example 443
  • Path : API path, example "/api"
  • Datestamp : Date/time when added to the table

Files

  • FileID : SHA512 hash of the Plaintext (PRIMARY KEY)
  • Plaintext : The content of the file (UTF8)
  • Datestamp : Date/time when added to the table

Keys

  • MainKeyID : Signature key (PRIMARY KEY)
  • SubKeyID : Encryption key
  • PublicKeyring : Contains public keys
  • SecretKeyring : Contains secret keys (only set for your own bank, NULL for others)
  • BankID : The BankID which the keys belong to
  • Datestamp : Date/time when added to the table
  • PrimaryKey : Only set to TRUE for one row per BankID, other keys are still valid, but this key is used when creating new messages

Messages

  • MessageID : SHA512 hash of the Cipherdata (PRIMARY KEY)
  • FileID : The hash of the file send in the message
  • FromBankID : The bank who sent the message
  • ToBankID : The bank who received the message
  • Cipherdata : The encrypted and signed message
  • DeliveryReceipt : The encrypted and signed delivery receipt
  • Datestamp : The date/time when the message was created
  • Delivered : The date/time when the message was delivered

Database functions

Create_Message(Plaintext, FromBankID, ToBankID)

Create_Message() takes the plaintext context of a file as input and prepares
an encrypted message signed by FromBankID which can be only decrypted by
ToBankID. If the message already exists, the existing data is reused.
An error is returned if the secret key of FromBankID or the public key
of ToBankID can not be located in the database.

The return value is the message id of the message.

Get_Message(MessageID)

Given a message id as input, Get_Message() returns the ASCII armored PGP
message. This data can then be HTTPS POSTed to the Receive_Message API method
of ToBank.

Receive_Message(Ciphertext text)

Receive_Message() decrypts and verifies the signature of the input message.
The message's details are written to the Messages table, and information
about the file and its plaintext contents are written into the Files table.
This function will raise an error if:

  1. The secret key counterpart of the public key used to encrypt the
    message is not present in the table Keys.

  2. The public key counterpart of the secret key used to sign the message
    is not present in the table Keys.

  3. The message is corrupt or the signature can not be verified.

The return value is a delivery receipt, which should be then used as the
contents of the response to the caller of the Receive_Message API method.

Decode_Delivery_Receipt(DeliveryReceipt text)

Decode_Delivery_Receipt() decrypts and verifies the given delivery receipt,
where the keys involved and the plaintext should match a row in Messages. If
so, the Message has been successfully delivered, and the
Messages.DeliveryReceipt and Messages.Delivered columns are set.

Installing and building .deb packages for installation

The repository includes scripts for building debian/ubuntu packages for the
bankapi and the required pgcrypto extensions (in PostgreSQL) in order to run
the code.

If you are running a different version of PostgreSQL then 9.3 then replace the
version in the commands below with the appropriate version. If you are running
the default version in Debian you can omit the version extension of the
packages names.

  • sudo apt-get -y build-dep postgresql-9.3
  • sudo apt-get -y install postgresql-server-dev-9.3 postgresql-9.3 apache2 python-psycopg2 python-requests
  • make

This should produce two deb files, one for bankapi and one for the pgcrypto
extension.

bankapi-1.0.deb

Package contains the command line tools for sending messages
(/usr/bin/bankapi), SQL needed for creating the bankapi in postgres and
installes a CGI as an endpoint for receving incoming communication messages.

The installation of the module installs and activates the CGI script. It will
be available under http://localhost/bankapi .

The installation does not finish the installation of the database but leaves
this as a manual task. Follow the following steps for a default database
installation:

  • cd /usr/share/bankapi
  • sudo -u postgres createdb bankapi
  • sudo -u postgres psql --dbname=bankapi --single-transaction --no-psqlrc --file=install.sql
  • Make sure www-data user can connect to the bankapi database, this can for
    instance be done by adding the following line where appropriate in the active
    pg_hba.conf file: local bankapi www-data peer
  • To optionally install the test bank data: sudo -u postgres psql --dbname=bankapi --single-transaction --no-psqlrc --file=testdata/index.sql

postgresql-pgcrypto-openpgp-9.3.deb

This is an extension to the pgcrypto PostgreSQL extension. The extension only
installs with the extended functions, all functions normally in pgcrypto is
still accessed from the standard pgcrypto extension. The extension is called
pgcrypto_openpgp.