weekly of 20180401

工具技巧

系统设计

  • Performance Under Load : Netflix关于如何做过载保护的文章,其实这个topic,个人感觉也研究了一段时间,包括排队论等都做了一些分析。文章的核心思路是复用TCP拥塞控制的算法, 开始以较低流量去尝试,在流量逐渐增大的过程中,通过一些参数指标评估服务是否达到瓶颈,如果是,则流量回退(类似于拥塞窗口减少)($newLimit = currentLimit × gradient + queueSize$)。同时也直接开放了相关的lib库, 支持Java/Grpc等,可以关注。

  • Introducing Cloudflare Workers: Run JavaScript Service Workers at the Edge : CloudFlare的Service Worker概述,赋予了业务在Edge Node(类似于CDN)执行代码的能力,后端的同学可以通过这篇文章Service Worker 应用详解了解浏览器service worker的大概机制;整体而言,个人感觉思路和创新都是有的,不过对于应用场景还需要深入和进一步的思考

  • Using Machine Learning to Improve Streaming Quality at Netflix : 通过ML的方法,来预估网络的质量和延迟情况,先mark

琐事小记

其他

  • Steinhaus Longimeter : mark,一个测量曲线长度的办法,非常精巧,先mark

  • 从抄书到开源之巅:章亦春的程序人生 : 非常敬佩的工程师, 每个成功故事的历程都有所不一样,但是持续努力奋斗是永恒的主题;

  • 西甲风云21:铁血军团,马德里竞技 : “催人泪下的卡尔德隆,这是我的家。它教会我怎样成长,怎样忍耐,怎样生活,怎样面对困境。不管贫富,我们永远是第一!Forza Atleti!”, 有点跑题的文章,不过写得很好,也mark

  • 聊聊Chaos Engineering的历史、原则和最佳实践 : 我的理解Chaos Engineering应该属于SRE的一部分,其采用特殊的方法,去验证系统的容灾能力,评估系统的可用性。随着分布式系统的日趋复杂,这样的需求也会愈加强烈。

  • 既练轻功也练内功——面对风口的正确姿势 : 每个人都会面临各种选择和权衡,如何合适的机会和风口,让自己的职业生涯有进一步提升,是个需要深思的问题, 作者建议的三个原则,学会预测,需找开鱼刀,练轻功之前先修炼好内功, 可以采纳

  • Engineering Blogs : 一些公司的技术blog的list,感觉可以通过收藏夹或者其他的可以序列话的方式提供。

Crypto101读书笔记

cryptography

最近要把去年的读书笔记补齐~

电子书Crypto 101是我个人感觉最好的关于密码学的入门笔记; 深入浅出的介绍了整个密码学体系的各类算法,此文为此书的读书笔记

分层体系

  • 第一层: 最底层是基础算法原语的实现, 比如: md5, AES, RSA, SHA256等

  • 第二层: 选定参数后,划分为符合密码学标准分类的算法, 几个基本能力:

    • 块加密算法
    • 流加密算法
    • 密钥交换算法
    • 公钥加密算法
    • MAC算法
    • 签名算法
  • 第三层: 基于标准分类算法进一步组合而成的半成品,比如说对称传输组件例如aes-128-cbc + hmac-sha256, 认证密钥协商算法rsassa-OAEP + ecdh-secp256r1

  • 第四层: 用各种组件拼装而成的各种成品密码学协议/软件, 比如TLS协议等

这里先介绍第一/二层的常见技术和方法,以后再深入分析第四层的业务应用。

标准密码学概述

Block ciphers

  • 定义:

A block cipher is an algorithm that allows us to encrypt blocks of a fixed length. It provides an encryption function E that turns plaintext blocks P into ciphertext blocks C, using a secret key k:

$$ C = E(k, P) \ \ encrpytion $$
$$ P = D(k, C) \ \ decryption $$

一般情况下, 明文和密文的长度是一样的,这个是由密钥控制的;

常见放的对称加密算法有: AES(Advanced Encryption Standard) 和 相对比较老的 DES3DES

可以预见块加密算法有两个比较大的问题,具体包括:

1) 块加密算法只能加密固定长度的信息,这个并不能很好应用于现实世界,所以我们需要引入Stream ciphers

2) 密钥非常重要,但我们仍会面临着如何在一个不安全的通道上面交互密钥;这个在key exchange protocol里面会介绍其解决方案

Stream Ciphers

还是先看定义,英文如下:

“A stream cipher is a symmetric-key encryption algorithm that encrypts a stream of bits. Ideally, that stream could be as long as we’d like;”

如何实现, 初步的想法就是基于Block Ciphers去实现,将超长的文本切分为固定长度的子串,再分别加密。如何将block ciphers变成stream ciphers是需要精细考量的。比如最简单的ECB模式(Electronic Code Book Mode), 其过程大概如下:

ECB加密过程

ECB解密过程

但是这个模块是的弱点非常明显, 比如攻击者可以方便地做流量重放,而且密文和原始明文的顺序也是一一对应,容易被攻击。

我们可以考虑其他的几个方式,包括:

  • CBC : “plaintext blocks are XORed with the previous ciphertext block before being encrypted by the block cipher.”, 同时对于第一个block,我们通过引入初始向量解决(initialization vector, IV) ,其中IV我们要求满足不可预测的要求,所以一般用CBC模式加密的时候还需要双方达成IV的一致这个步骤(后续详解)

如下是CBC的加解密过程示意图:

CBC加密过程
CBC加密过程

CBC模式对于初始向量有较大依赖,一旦IV被攻击者预测等,整个加密的安全性也难以得到保障

一些数学形式化的说明如下,可以简单参考

Mode Formulas Ciphertext
ECB $Y_i = F(Plaintext_i, Key)$ $Y_i$
CBC $Y_i = Plaintext_i XOR \ Ciphertext_{i-1}$ $F(Y,key); Ciphertext_0 = IV$
PCBC $Y_i = Plaintext_i XOR \ (Ciphertext_{i-1} XOR \ Plaintext_{i-1})$ $F(Y,key); Ciphertext_0 = IV$

虽然通过CBC等模式,我们可以实现对字节流的加密,但是如何达成密钥的一致性依旧是个问题,所以我们可以看下Key Exchange Protocol

(如上的内容和表格都来自于Wikipedia:Block cipher mode of operation)

Key exchange

目标大概如下: “Key exchange protocols attempt to solve a problem that, at first glance, seems impossible. Alice and Bob, who’ve never met before, have to agree on a secret value. the channel they use to communicate is insecure: we’re assuming that everything they send across the channel is being eavesdropped on.”

该协议又称Diffie-Hellman算法, 一般有两个实现方式,包括discrete logarithmselliptic curves,前者相对来说比较好理解,下面详细说明:

离散对数问题基于如下的假设,对于等式:

$$ g^x \equiv y (mod \ p) $$

已知$g,p$, 给定$x$计算$y$很容易,反之则很难; 则我们可以推理如下:

对于消息交换者Alice, Bob 和 窃听者Eve, 他们在传输消息时候有($r_a$和$r_b$是A,B产生的随机数), 则他们初步可以发送如下两个消息:

$$ m_a \equiv g^{(r_a)}(mod\ p)$$

$$ m_b \equiv g^{(r_b)}(mod\ p)$$

依照约定,可以产生密钥$s$

$$ s = (g^{(r_a)})^{r_b} (mod\ p)$$

这两个消息,三个人都能看见;但是对Alice而言,他收到了$m_b$我们有:

$$ s = m_b^{r_a} (mod\ p)$$

对Bob同理;

$$ s = m_a^{r_b} (mod\ p)$$

但是对于只有$m_a,m_b,g,p$的Eve来说是不能计算出$s$的, 即便$m_a, m_b$相乘:

$$ t = m_a * m_b (mod\ p) = g^{r_a + r_b} (mod\ p)$$

如下是从Wikipedia: 迪菲-赫尔曼密钥交换摘录的示意图:

DH示意图

这个算法很优雅,但是存在很大的问题,就是中间人攻击。 所以我们需要一些新的基础能力,比如说去验证Alice和Bob的真假, 去保障我们消息的完整性。这个后续再讨论如何去保障。

Public-Key encryption

定义: “People can encrypt information intended for you by using your public key. the information is then impossible to decipher without your private key.”

这里咬文嚼字一翻,公钥加密算法并不等同与『公钥算法』,后者的应用场景会更多,包括:

  • 密钥交换
  • 加密信息
  • 数字签名

常见的公钥算法包括:

  • RSA encryption algorithm (PKCS#1)
  • Various elliptic curve techniques
  • Diffie–Hellman key exchange protocol
  • ElGamal

现在主流的是RSA和基于椭圆曲线的加密算法。

公钥算法是一个非常大的进步,而且直接感觉,好像所有的密码学问题都可以通过公钥算法解决。但是从现实角度而言,但是仅仅依靠此还不能构建健壮的安全体系,具体的问题包括:

  • 作用范围 : 公钥加密算法只能加密一小块的数据
  • 性能问题,这个可以通过混合加密体系解决(公钥+对称加密)
  • 合法性验证问题: 虽然我们可以加密解密任何消息,但是我们并不知道此消息是否来自真的发送者

对与最后一个问题,我们需要一个机制去验证消息的合法性(完整性和不可否认性);常见的做法是在发送消息的时候,增加一些额外信息,这次信息只能是正确的发送者才能构造的;同加密算法一样,验证消息机制同样有对称和非对称体系。如果发送方和接收方用同一个key进行验证,我们一般称为MAC(message authentication codes);如果用不同的key进行验证,我们则称为signature(数字签名)

在介绍着两者之前,我们先简单介绍他们的基础支持体系 – hash function

Hash functions

Hash函数一般而言是对一段文本的摘要(digest), 用于加密验证的hash function一般有更高的要求, 不再赘述,常见的有如下几个算法:

  • MD5 : 不建议了
  • SHA-1 : 不建议范畴了
  • SHA-2 : 现在通用的
  • SHA-3(Keccak) : 未来的标准

可以区别和注意的是SHA2SHA3,后者的设计理念和前者完全不一致,在硬件上面的性能也更为高效。可以参看Wikipedia:SHA-3 对比不同hash function的特性,表格太大,就不直接摘录了。

Message authentication code

定义: A Message authentication code (MAC) is a small bit of information that can be used to check the authenticity and the integrity of a message. else codes are often called ”tags”

也就是说在双方共享$K_m$的情况下,需要达成一种协议,包括接收方能够快速的验证$P$的完整性。本质而言,就是需要一个$F$, 支持如下的模式:

$$ t = F(P, K_m)$$

对于如何将MAC和加密消息组合,有三种不同的方式,包括:

  • Authenticate and encrypt : 分别进行消息验证和加密,类似于 $C = E(K_C, P), t = MAC(K_m, P)$, 同时发送$C$和$t$, SSH采用该方式
  • Authenticate, then encrypt : 对消息进行验证,其次和明文组合一起后加密发送,如下方式 $t=MAC(K_m,P), C=E(K_C,P||t)$, 只要发送$C$ 就可以了, TLS采用的方式
  • Encrypt, then authenticate : 先加密, 对加密串算MAC,后一起发送,类似$C=E(K_C,P), t=MAC(K_M,C)$, IPSec采用的方式

普遍认为第三种方式是最好的,因为在解密之前就可以验证消息的合法性;

对于MAC的具体实现方式,本质而言,就是需要一个$F$, 给定密钥

  • 简单的方式: $t=H(k||m)$, H可以选择一个hash function, 这类组合方式有较大的安全风险(不展开)
  • HMAC(Hash-based Message Authentication Code
    ) : 其是通过特殊计算的消息验证码,有着更好的安全保障。可以参看其RFC文档
  • One-times MAC

从上面可以看到, 我们现在对于加密消息验证是当做两个独立的操作,但是在现实生活中,我们很少会独立应用这两个场景,所以现在也提出了AEAD(Authenticated Encryption with Associated Data), 其能支持”验证加密”(authenticated encryption), 将AE的能力以直观的方式提供给业务方。

Signature algorithms

简单定义如下:

A signature algorithm is the public-key equivalent of a message authentication code. It consists of three parts:

  1. a key generation algorithm, which can be shared with other public-key algorithms
  2. a signature generation algorithm
  3. a signature verification algorithm

很自然而然的我们可以想到RSA可以用于数字签名

下面我们简单分析另外一个数字签名算法DSA, 其分为两个缓解,一个是参数选择,另外一个是生成公钥私钥; 具体如下:

TODO, 补充

DSA Parameter generation

Key generation

如下是常见的签名算法(Wikipedia: Digital signature )

  • RSA-based signature schemes, such as RSA-PSS
  • DSA and its elliptic curve variant ECDSA
  • Edwards-curve Digital Signature Algorithm and its Ed25519 variant.

通信过程概述

通过如上的分析,我们可以认为拥有如下几个能力:

  • 对称加密能力 : 给定一个key,将内容进行加密的能力
  • 消息散列 : 通过一个key,可以验证消息的完整性和认证
  • 非对称加密能力: 可以通过公钥密钥进行加解密
  • 数字签名 : 通过非对称密钥验证消息完整性和认证

基于此,可以构建上层更复杂丰富的业务场景,比如说TLS; 这个里面的细节比较多,我们在以后的文章详细介绍TLS的协议流程。

weekly of 20180318

工具技巧

系统设计

  • Protecting Against HSTS Abuse : 本文介绍了HSTS的另外一个缺点, 除了传统的设置HSTS不合理,可能导致源站不能访问之外。文章指出: 每为一个域名设置一个HSTS, 其实就相当于给这个域名种下永久cookie。基于次, 我们可以通过N个不同的域名(比如a/b/c/d/e),并且以类似于0/1组合的方式设置HSTS, 这样的话,我们就可以唯一标识一个具体的用户。基于次,在用户信息收集,广告追踪等方面,都可以发挥一定效果。webkit同时也给出了他们的解决方案,比如控制相同域名请求等, 感觉治标不治本。其实进一步,可以分析和感觉,网络攻击的自由和灵活性。

  • Understanding CPU port contention. : mark,作者是做编译器设计的,blog里面有不少文章介绍performance optimizations and analysis in C/C++

琐事小记

  • Does grep work differently on OSX : 大家知道MacOS是基于FreeBSD的,所以其内置的grep命令,也是不支持Perl regex语法,一个解决方案是用homebrew去安装, 会生成ggrep的新的支持GNU Grep规则的命令

其他

  • 推荐10款流行的密码破解工具 : 关注下, 后续找地方实践

  • 霍金用的那套语音合成软件,现在你也可以尝鲜了 :

  • 信息安全书单推荐 : 可以重点关注安全技术分类下面的那些书,虽然感觉看了一半,但是缺乏实践,所得一般

  • AWS 公用数据集 : 有兴趣的可以关注下, 建议可以关注Amazon Bin Image Dataset, GDELT on AWS(Global Database of Events, Language and Tone)等

  • Coping with the TCP TIME-WAIT state on busy Linux servers : 14年的一篇老文章,今天才看到,个人感觉是对Linux TIME_WAIT等问题和解决方案介绍的比较系统的文章。简而言之,TIME_WAIT状态, 一则可以避免网络中丢失包的错误ACK,同时也能解决FIN->ACK时ACK丢失的问题。但是正常情况下, TIME_WAIT状态要保留2MSL(差不多60s), 这个对于固定的四元组(src ip, src port ,dest ip, dest port)来说, port资源会不足,从而导致性能上面会有影响。而一旦使用tcp_tw_recycle flag,就会存在较大的副作用, 比较建议的是tcp_tw_reuse, 但是其要求开启tcp timestamp flag, 在NAT网络下兼容性较差。同时也推荐下作者的blog,有不少非常靠谱的文章。

weekly of 20180311

工具技巧

系统设计

琐事小记

其他

nginx 1.13.10 版本说明

Feature List

对SSI模块增强,支持set指令,允许插入任何变量

  • Feature: the “set” parameter of the “include” SSI directive now allows writing arbitrary responses to a variable; the “subrequest_output_buffer_size” directive defines maximum responsesize.

通过 CLOCK_MONOTONIC方式获取时间, 避免时间回转

  • Feature: now nginx uses clock_gettime( CLOCK_MONOTONIC ) if available, to avoid timeouts being incorrectly triggered on system time changes.

支持日志输出时不做字符转义

  • Feature: the “escape=none” parameter of the “log_format” directive.

支持打印ALPN变量情况

  • Feature: the $ssl_preread_alpn_protocols variable in the ngx_stream_ssl_preread_module.

引入gRpc支持

  • Feature: the ngx_http_grpc_module.

快速说明

  • CLOCK_MONOTONIC方式获取时间 : 正常系统提供两个类型的时间
    • time-of-day : 俗称墙上时间,但是墙上时间会通过类似于NTP的协议同步时钟,这个有可能导致时间回退,
    • CLOCK_MONOTONIC时间 : 理论上对和time-of-day一致,其主要特点是, 基本同步时钟后发现自己时间过快,也不会回退,而是按照一定的算法自己缓慢增加,慢慢保持一致, 也就是能保障这个时间总是单调(MONOTONIC)的
    • 这个问题是分布式系统经常会碰到的,可以深入了解
  • “escape=none”支持:
    • 简单来说, 之前nginx默认对输入的日志变量会进行转义,转义的字符主要是Nginx认为不可见的那部分, 这部分代码实现很精巧,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
static uintptr_t
ngx_http_log_escape(u_char *dst, u_char *src, size_t size)
{
ngx_uint_t n;
static u_char hex[] = "0123456789ABCDEF";
//建立`escape`的bitmask数组, 一个有 32 * 8 = 256个bit
//如果对于bit被mask为1,表明需要转义
static uint32_t escape[] = {
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
/* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
0x00000004, /* 0000 0000 0000 0000 0000 0000 0000 0100 */
/* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
0x10000000, /* 0001 0000 0000 0000 0000 0000 0000 0000 */
/* ~}| {zyx wvut srqp onml kjih gfed cba` */
0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
};
while (size) {
// 判断其mask位是否为1
// *src >> 5 为去其高3位,用于获取数组的便宜量
// 1U << (*src & 0x0f) 为获取具体在数据bit mask的位置
if (escape[*src >> 5] & (1U << (*src & 0x1f))) {
*dst++ = '\\';
*dst++ = 'x';
*dst++ = hex[*src >> 4];
*dst++ = hex[*src & 0xf];
src++;
} else {
*dst++ = *src++;
}
size--;
}
return (uintptr_t) dst;
}
  • ssl_preread_alpn_protocols变量 :
    • 这里面大家可以关注ALPN协议,他和NPN都是用于在TLS交互的时候进行协议的协商, 可以关注之前的文章为什么我们应该尽快支持 ALPN?
      ,大概区别如下:
      • NPN 是服务端发送所支持的 HTTP 协议列表,由客户端选择;而 ALPN 是客户端发送所支持的 HTTP 协议列表,由服务端选择;
      • NPN 的协商结果是在 Change Cipher Spec 之后加密发送给服务端;而 ALPN 的协商结果是通过 Server Hello 明文发给客户端;
    • 可以总结为ALPN是趋势,也是未来的标准,但是短期内各方厂商的支持情况并不理想

weekly of 20180304

工具技巧

系统设计

琐事小记

其他

weekly of 20180225

工具技巧

系统设计

  • Paper review. IPFS: Content addressed, versioned, P2P file system : IPFS最近被普遍认为会是一个改变下一步互联网的技术,其非中心化的特性以及基于内容hash的索引使得我们在内容安全,查找等多方面都有进一步的优势,作者肯定其思路和创意,同时也提出了一些对IPFS的看法,比如说P2P的网络如何和移动设备关联推广起来, P2P的内容管理对现在中心化的产品以及交互的改变(比如Googl如何索引内容)等, 可以加深对整个IPFS的理解和认识

  • Scalable Bloom Filters(PDF) : 作者介绍了一个可扩展的布隆过滤器方法, 核心思路是通过增加新的slot来构建一定数量和准确率要求下的过滤器

琐事小记

其他

weekly of 20180218

日本-富士山

工具技巧

  • Enforcing the use of SRI : SRI策略是CSP新引入的一个策略, 通过SRI可以保障外链的资源(包括js/css), 要和代码里面的签名哈希一致, 避免受到这个方面的攻击影响, 可以同时参考作者的另外一篇文章Subresource Integrity: Securing CDN loaded assets

  • Inspector: A drop-anywhere C++ REPL : REPL(Read–Eval–Print Loop), also known as an interactive toplevel or language shell, 他支持对C++代码做交互式的处理,类似于GDB里面的debug状态,可以参看Hacker News上面的讨论

  • LATENCY : Global latency testing tool, 可以测试不同域名在全球不同区域的响应速度

  • JMESPath : JMESPath is a query language for JSON, 类似于JQ,不过语法上面好像更复杂

系统设计

  • My Favourite Secret Weapon – strace : 文章系统介绍strace的用法以及作用, 不过从这篇文章来看strace Wow Much Syscall, strace在机制原理上面存在性能瓶颈(通过ptrace的方法,没遇到系统调用就暂停源进程,其后分析数据), 故建议使用类似于perf trace, sysdig之类的工具

  • Nginx HTTP/2 server push support : Nginx也要支持Http 2的server push机制, 原文是具体的代码实现,后者的hacker news上面的讨论,其实对http2的完整支持,nginx相对而言还是比较落后的,但是一旦支持之后,个人决定对于产品的生态链的收敛还是非常有意义的

  • TOP 10 MySQL 8.0 features for DBAs & OPS : MySQL 8的一些新特性, 个人觉得可以关注的特性包括Removing Query Cache, Faster & More Complete Performance Schema (Histograms, Indexes, …) and Information Schema, Persistent Global Variables etc

  • How production engineers support global events on Facebook : Facebook Live On产品介绍其如何应对预期流量高峰(比如圣诞,新年)的方法和手段,包括常规的流量预估,压测,方法论上面没有太多新意

琐事小记

其他

  • The Two Faces of AMP : 本文讨论AMP的两面性,一方面,从技术方面,其提供的能力让web mobile端的体验有了质的提升,另外一方面,Google也说明会提升基于AMP网站的rank排序,对此多少web开发者持反对态度,这种捆绑销售与开放互联网的精神相悖

  • A BRIEF GLANCE AT HOW VARIOUS TEXT EDITORS MANAGE THEIR TEXTUAL DATA: 对于场景编辑器的buffer机制的概要说明, 类似于之前同样推荐的文章,建议大家重点关注Gap buffer

weekly of 20180211

日本-富士山

工具技巧

  • Here’s how Google Chrome’s new ad blocker works : 关于Chrome的广告防御系统的设计和构建, 可以了解整个Chrome反作弊体系的设计思路和理念;感觉Google做多系统和模块设计的系统化和组件化都很强,非常值得学习

系统设计

琐事小记

其他

weekly of 20180121

奥地利

工具技巧

  • SYN packet handling in the wild : 关于TCP SYN交互和实现的深入讨论,包括内核和应用程序对于syn flood, syn queue, accept queue的介绍

  • 揭秘超分辨率的正确打开方式 : 具体介绍超分图片背后的理念,以及在微信的应用和效果,手百现在也在推动此类的事情。对于超分的应用场景也做了比较好的分析和介绍

系统设计

  • The Death of Microservice Madness in 2018 : 对微服务化的又一次系统性概述,分析,对于希望或者想要设计更理想业务模式的同学而言,是个很好的思路学习机会,也有中文翻译版

  • Why TLS 1.3 isn’t in browsers yet : 随着TLS 1.3的规范落地,其业务落地也是需要重点考虑的问题,然而现实情况是,由于一些middlebox在实现等兼容性的问题, 浏览器其实并不能透明的从TLS 1.2升级到TLS 1.3, 作者具体分析了这里面的一些风险和问题, 包括协议设计上面的兼容性问题等等,整体下来可以加深对TLS协议的理解

  • 如何节省1T图片带宽? 解密极致图像压缩 : 腾讯的团队,分别介绍了在WebP, 自研WXAM, 以及guetzli的落地经验。两个总结, 一个是腾讯在这个方面还是做了较多的研究和分析的,文章分享的问题都是比较干货的;其次是, 虽然之前也考虑落地过guetzli, 但没有成功, 整体来说, 执行力还是太差了

  • Deemon:自动化CSRF安全检测框架 : 关于自动化CSRF攻击检测的设计理念, 一些东西没有完全理解,先mark

琐事小记

其他