FIDO U2F、FIDO2 和 CTAP 的关系

背景 2012 年,Yubico 和 Google 设计了 U2F 协议,第二年 U2F 成为 FIDO 组织的标准,之后加入了 NFC 的支持。之后,FIDO2 作为替代 U2F 的新标准产生,原来的 U2F 以兼容的方式成为了 CTAP1,而采用 CBOR 封装格式的 CTAP(CTAP2) 则是 FIDO2 的主要协议。 U2F 命令格式 U2F 定义了它的命令格式,基于 ISO7816-4 APDU(short APDU) : CLA INS P1 P2 Lc data Le 1 byte 1 byte 1 byte 1 byte 0-1 bytes variable length 0-1 bytes 比如 U2F_VERSION 就是: CLA INS P1 P2 Lc data Le 00 03 00 00 0 empty 00 返回的数据就是 U2F_V2 的 ASCII 加上 9000 的状态。

Read More

USB/IP 模拟 USB 设备

背景 2018 年的时候发过一篇博客,讲如何用 USB/IP 协议在两台 Linux 电脑之间共享 USB 设备。最近刚好有一个需求,就是针对一个现成的 USB device 的代码,通过 USB/IP 模拟出一个 USB 设备,然后进行调试。 USB/IP 协议 USB/IP 只有一个简略的文档,为数不多的使用 USB/IP 的代码,所以有一些细节没有说的很清楚,只能一点点去尝试。 首先,USB/IP 基于 TCP,端口号 3240 。客户端向服务端发送请求,服务端向客户端进行回应。 请求的类型:OP_REQ_DEVLIST OP_REQ_IMPORT USBIP_CMD_SUBMIT 和 USBIP_CMD_UNLINK 回应的类型:OP_REP_DEVLIST OP_REP_IMPORT USBIP_RET_SUBMIT USBIP_RET_UNLINK 工作的过程大概如下: OP_REQ_DEVLIST 请求获取设备列表 OP_REP_DEVLIST 返回设备列表 OP_REQ_IMPORT 请求 USB 设备 OP_REP_IMPORT 返回 USB 设备 USBIP_CMD_SUBMIT 发送 URB USBIP_RET_SUBMIT 返回 URB (先不考虑 CMD_UNLINK 和 RET_UNLINK) 其中前面四个比较简单清晰,所需要的字段也都是 Descriptor 中对应的字段。后面两个就相对复杂一些:URB data 的长度需要根据 endpoint 类型和 direction 共同决定。URB 实际上是 Linux 内核里的一个数据结构。

Read More

MIFARE Classic 上配置 NDEF

背景 最近买了一堆 NFC 的智能卡拿来测试,其中一张 MIFARE Classic 的总是在 iOS 上读不出来,无论是以 Tag 模式还是 NDEF 模式。于是通过一系列的研究,终于知道上怎么一回事,然后成功地把一个 MIFARE Classic 卡配置成了 NDEF。 背景知识 NFC 有很多协议,其中 MIFARE Classic 基于 ISO 14443-3 Type A 标准,里面有一些 MIFARE 的命令。通过这些命令,就可以控制 MIFARE Classic 卡的内容。具体来说,以我使用的 MIFARE Classic EV1 4K S70 为例,这篇文章会涉及到如下的背景知识: MIFARE Classic 内存布局 在 MIFARE Classic 中,有 Sector 和 Block 的概念,每个 Sector 有若干个 Block,其中最后一个 Block 是特殊的(称为 Sector Trailer),保存了这个 Sector 的一些信息:Key A、Access Bits、GPB 和 Key B。对于 Classic 4K,首先是 32 个有 4 blocks 的 sector,然后是 8 个 有 16 blocks 的 sector, 整体的内存布局大概是:

Read More

解释 BB84 协议

背景 这周密码学课程,来自 BUPT 的高飞老师讲了一下 qkd 里的 BB84 协议,老师讲得很好,我也想记录一下这个协议的流程和方法。我不是这方面的专业人士,如果有什么问题请指出。 背景知识 QKD(Quantum Key Distribution)目的是让通信双方获得同一个密钥,它需要同时需要量子信道和经典信道。其中经典信道被认为是可信的,它可以被监听,但不能被中间人攻击。 在 BB84(Charles H. Bennett and Gilles Brassard (1984))协议中,传输的是一个光子,它具有如下的特性: 可以用两个基去测量光子:➕️和✖️️,然后光子有四个偏振角度,分别是 ⬆️️ ⬇️️ ↘️️ ↗️️。定义一个二进制位和偏振角度的对应关系如下: 位 0 1 0 1 基 ➕️ ➕️ ✖️️ ✖️️ 偏振角度 ⬆️️ ⬇️️ ↗️️ ↘️️ 对于一个未知光子,可以用两种基进行测量,测量的结果: 偏振角度 ⬆️️ ⬇️️ ↗️️ ↘️️ 用➕️测量 0 1 0/1 0/1 用✖️️测量 0/1 0/1 0 1 这里的 0/1 表示有 50% 概率测得 0,有 50% 概率测得 1 。

Read More

在 k8s 中部署 code-server

实验了一下在 k8s 中部署 code-server,并不复杂,和之前几篇博客的配置是类似的: apiVersion: extensions/v1beta1 kind: Deployment metadata: name: code labels: app: code spec: selector: matchLabels: app: code replicas: 1 template: metadata: labels: app: code spec: volumes: - name: code-volume persistentVolumeClaim: claimName: code-pvc initContainers: - name: home-init image: busybox command: ["sh", "-c", "chown -R 1000:1000 /home/coder"] volumeMounts: - mountPath: "/home/coder" name: code-volume containers: - image: codercom/code-server:latest imagePullPolicy: Always name: code volumeMounts: - mountPath: "/home/coder" name: code-volume resources: limits: cpu: "0.

Read More

在 k8s 中部署 Drone 用于 CI

实验了一下在 k8s 中部署 CI,在 drone gitlab-ci 和 jenkins 三者中选择了 drone,因为它比较轻量,并且基于 docker,可以用 GitHub 上的仓库,比较方便。 首先,配置 helm: helm repo add drone https://charts.drone.io kubectl create ns drone 参考 drone 的文档,编写 drone-values.yml: ingress: enabled: true annotations: kubernetes.io/ingress.class: "nginx" cert-manager.io/cluster-issuer: "letsencrypt-prod" hosts: - host: drone.example.com paths: - "/" tls: - hosts: - drone.example.com secretName: drone-tls env: DRONE_SERVER_HOST: drone.example.com DRONE_SERVER_PROTO: https DRONE_USER_CREATE: username:YOUR_GITHUB_USERNAME,admin:true DRONE_USER_FILTER: YOUR_GITHUB_USERNAME DRONE_RPC_SECRET: REDACTED DRONE_GITHUB_CLIENT_ID: REDACTED DRONE_GITHUB_CLIENT_SECRET: REDACTED 需要首先去 GitHub 上配置 OAuth application,具体参考 drone 的文档。然后,生成一个 secret,设置 admin 用户并只允许 admin 用户使用 drone,防止其他人使用。然后应用:

Read More

在 k8s 内用 Cert Manager 配合 Nginx Ingress Controller 配置 Let's Encrypt HTTPS 证书

上一篇博客讲了 nginx ingress 的配置,那自然第一步要配上 https。首先配置 cert-manager: $ kubectl create namespace cert-manager $ kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v0.14.1/cert-manager.crds.yaml $ helm repo add jetstack https://charts.jetstack.io $ helm repo update $ helm install \ cert-manager jetstack/cert-manager \ --namespace cert-manager \ --version v0.14.1 然后,配置 Cluster Issuer,应用以下的 yaml: apiVersion: cert-manager.io/v1alpha2 kind: ClusterIssuer metadata: name: letsencrypt-prod namespace: cert-manager spec: acme: email: example@example.com server: https://acme-v02.api.letsencrypt.org/directory privateKeySecretRef: name: letsencrypt-prod solvers: - http01: ingress: class: nginx 然后在 ingress 里面进行配置:

Read More

在 TKE 上配置不使用 LB 的 Nginx Ingress Controller

背景 想要在 k8s 里面 host 一个网站,但又不想额外花钱用 LB,想直接用节点的 IP。 方法 首先安装 nginx-ingress: $ helm repo add nginx-stable https://helm.nginx.com/stable $ helm repo update $ helm install ingress-controller nginx-stable/nginx-ingress --set controller.service.type=NodePort --set controller.hostNetwork=true 这里给 ingress controller chart 传了两个参数:第一个指定 service 类型是 NodePort,替代默认的 LoadBalancer;第二个指定 ingress controller 直接在节点上监听,这样就可以用节点的公网 IP 访问了。 然后配一个 ingress: apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: ingress-example annotations: kubernetes.io/ingress.class: "nginx" spec: rules: - host: example.com http: paths: - path: / backend: serviceName: example-service servicePort: 80 然后就可以发现请求被正确路由到 example-service 的 80 端口了。

Read More

在 sbt 中 fork 并且并行运行测试

问题 最近在 sbt 使用遇到一个问题,有两个测试,分别用 testOnly 测试的时候没有问题,如果同时测试就会出问题,应该是全局的状态上出现了冲突。一个自然的解决思路是 fork,但是 sbt 默认 fork 之后 test 是顺序执行的,这会很慢。所以搜索了一下,找到了 fork 并且并行测试的方法。 解决方法 解决方法在 sbt 文档中其实就有(原文)。简单来说就是:把每个 test 放到单独的 TestGroup 中,每个 TestGroup 分别用一个 forked JVM 去运行;然后让 sbt 的并行限制设高一些: // move each test into a group and fork them to avoid race condition import Tests._ def singleTests(tests: Seq[TestDefinition]) = tests map { test => new Group( name = test.name, tests = Seq(test), SubProcess(ForkOptions())) } Test / testGrouping := singleTests( (Test / definedTests).

Read More

在命令行中进行 Vivado 仿真

想要在命令行里进行 Vivado 仿真,所以查了下 Xilinx 的 UG900 文档,找到了命令行仿真的方法。首先是生成仿真所需的文件: # assuming batch mode open_project xxx.xpr set_property top YOUR_SIM_TOP [current_fileset -simset] export_ip_user_files -no_script -force export_simulation -simulator xsim -force 可以把这些语句放到 tcl 文件里然后用 batch mode 执行。执行成功以后,会在 export_sim/xsim 目录下生成一些文件。里面会有生成的脚本以供仿真: cd export_sim/xsim && ./YOUR_SIM_TOP.sh 默认情况下它会执行 export_sim/xsim/cmd.tcl 里面的命令。如果想要记录 vcd 文件,修改内容为: open_vcd log_vcd run 20us close_vcd quit 这样就可以把仿真的波形输出到 dump.vcd 文件,拖到本地然后用 GTKWave 看。更多支持的命令可以到 UG900 里找。

Read More