Compiling C/C++ project on jailbroken iOS devices (e.g. iPhone, iPad or iPod)

Recently, I am trying to build a portable web server on my old iPhone4 (iOS v7.1.2), and need a Vim v7.4 (with Python, Ruby and Lua support) for my remote editing/coding, but the BigBoss (only v7.1) and Radare (only v7.3-1) can’t help. So I have to work it out by myself, let’s see how.

0. Assumption

I am assuming you have a jailbroked iDevice and have basis knowledge about Cydia, if not, pls follow this TaiG jailbreak tutorial and this pic Add Source

1. Preparation

Search and install require packages after adding sources into Cydia.

1.1 Add Cydia Sources

  • (It’s the only source I can get fake-libgcc, kindly let me know if you have another new one.)

1.2 Search and/or install Packages

  • BigBoss Recommended Tools

    • (A bunch of useful tools)
  • Darwin CC Tools (v286-8, iOS compilation toolchain)

  • fake-libgcc (v1.0-2, GCC compilation toolchain. DO NOT upgrade/remove it even Cydia always prompt you to upgrade with libgcc)

    • fake-libgcc
    • GNU C Compiler
    • iphone-gcc Headers
  • Lua(v5.3.0-1):

  • Ruby(v1.9.2-p0-10):

  • Python(v2.7.6-3):

    Since the Python in Cydia’s sources is outdated, so need to install it manually.

    1. SSH to your iDevice with root ID
    2. Download Python DEB to /var/root/dl/

      curl -Ok /var/root/dl/```


      curl -Ok /var/root/dl/
    3. Install it

      dpkg -i /var/root/dl/python_2.7.6-3_iphoneos-arm.deb
  • iPhoneOS7.1.sdk

    You have 2 opthions to have it:

    1. Extracted from Xcode 5.1.1 dmg:




      and from



    2. Or simply clone from my repo (crt_externs.h is ready):

      git clone /var/root/dl/

2. Compilation

Make a place for binaries and other stuffs.

mkdir -p /var/root/dl/vimbuilt/share

Create a with following content for Make, Make will read it while makeing Makefiles.

nano /var/root/dl/local/share/

Content of

CPPFLAGS='-I/private/var/root/dl/iPhoneOS71SDK/usr/include -I/private/var/root/dl/iPhoneOS71SDK/usr/include -F/private/var/root/dl/iPhoneOS71SDK/System/Library/Frameworks'
LDFLAGS='-L/private/var/root/dl/iPhoneOS71SDK/usr/lib -L/private/var/root/dl/iPhoneOS71SDK/usr/lib -L/private/var/root/dl/iPhoneOS71SDK/usr/lib/system -F/private/var/root/dl/iPhoneOS71SDK/System/Library/Frameworks'

Now the folder structure:

└── share
    └──  # Configurations to let Make know 

Fetch the latest source code of Vim

git clone /var/root/dl/vim74src

Go to the source code folder, you will see a configure files is over there.

cd /var/root/dl/vim74src/src

Then run this command to build Makefiles

./configure --with-features=huge --disable-darwin --enable-gui=no --without-x --enable-multibyte --enable-luainterp --enable-pythoninterp --enable-rubyinterp 

–diable-darwin was required to disable trying to use the Carbon Framework, which isn’t available on iOS.

You will see

configure: loading site script /var/root/dl/vimbuilt/share/
configure: loading cache auto/config.cache
checking whether make sets $(MAKE)... (cached) yes
checking for gcc... (cached) gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for GCC 3 or later... yes
checking whether we need -D_FORTIFY_SOURCE=1... yes
checking linker --as-needed support... no
configure: creating auto/config.status
config.status: creating auto/
config.status: creating auto/config.h
config.status: auto/config.h is unchanged

Error info. will be logged to /var/root/dl/vim74src/src/auto/config.log if any.

and run this to start comilation

make && make install

Then Copy the /usr/bin/<vim-related-programs>, /usr/share/vim/ & /usr/share/man/ to /var/root/dl/vimbuilt/

Finally, the binaries, manual and other stuffs will be place to /var/root/dl/vimbuilt

├── bin                   # Vim's binaries
│   ├── ex -> vim
│   ├── rview -> vim
│   ├── rvim -> vim
│   ├── view -> vim
│   ├── vim
│   ├── vimdiff -> vim
│   ├── vimtutor
│   └── xxd
├── deb
│   ├── DEBIAN
│   │   └── control
│   └── usr
│       ├── bin            # Currently, empty
│       └── share          # Currently, empty
└── share
    ├── man                # Vim's manual
    └── vim
        └── vim74

In this moment, you may feel free to copy the bin/* to /usr/bin/, share/* to /usr/share/, that will work perfectly. But I will show you how to packing our work into a .deb file for further distribution. Keep going~

3. Building .deb package

Make a place for packing.

mkdir -p /var/root/dl/vimbuilt/deb/DEBIAN
mkdir -p /var/root/dl/vimbuilt/deb/usr

We need to create a control with following content for dpkg command.

nano /var/root/dl/vimbuilt/deb/DEBIAN/control

Content of control:

Package: io.github.neotan
Name: Vim v7.4
Version: 7.4
Section: Vim
Maintainer: Your Name <Your email or website>
Architecture: iphoneos-arm
Description: Vim v7.4 (with Python2.7, Ruby1.1 and Lua5.3 support)
Author: Your Name <Your email or website>
Sponsor: Your Name
Replaces: Vim (<= 7.4)

Replaces: Vim (<= 7.4) means will replace current existing/installed Vim if it’s version lower than our new version.

Now the folder structure:

├── bin              # Auto created by Make, for storaging binaries.
├── deb
│   ├── DEBIAN
│   │   └── control  # For building .deb file with dpkg command later
│   └── usr
└── share
    └──  # Configurations to let Make know 

And the vimbuilt/bin and the vimbuilt/share are the major things, the vimbuilt/deb is the place we start packing, so put them together:

cd /var/root/dl/vimbuilt
cp -R bin deb/usr/
cp -R share deb/usr/

The structure looks like this before building packge:

│   └── control
└── usr
    ├── bin
    │   ├── ex -> vim
    │   ├── rview -> vim
    │   ├── rvim -> vim
    │   ├── view -> vim
    │   ├── vim
    │   ├── vimdiff -> vim
    │   ├── vimtutor
    │   └── xxd
    └── share
        ├── man
        │   ├── fr
        │   ├── fr.ISO8859-1
        │   ├── fr.UTF-8
        │   ├── it
        │   ├── it.ISO8859-1
        │   ├── it.UTF-8
        │   ├── ja
        │   ├── man1
        │   ├── pl
        │   ├── pl.ISO8859-2
        │   ├── pl.UTF-8
        │   ├── ru.KOI8-R
        │   └── ru.UTF-8
        └── vim
            └── vim74

Build .deb package.

dpkg -b deb vim74.deb

Ignore these warning.

warning, `deb/DEBIAN/control' contains user-defined field `Name'
warning, `deb/DEBIAN/control' contains user-defined field `Author'
warning, `deb/DEBIAN/control' contains user-defined field `Sponsor'
dpkg-deb: building package `io.github.neotan' in `vim74.deb'.
dpkg-deb: ignoring 3 warnings about the control file(s)

Install new Vim from .deb package:

dpkg -i vim74.deb

Check the Vim version and features

vim --version

Now you will see +Python, +Lua, +Ruby tags

That’s it. Let me know if you built any funny tool. Enjoy compiling! Cheers!

References & Thanks

Thanks for following contributors of every threads! I can’t make above blog without them!

Objective-C 的属性及其特性(Property and its attributes)

看到 Objective-C 里@property后面那一串nonatomic/atomicstrong/weakreadwrite/readonlycopy确实有点蒙圈,转头问度娘,她嘿嘿一笑:你上周减仓了么?

忍住一口老血,寻遍 Google,Stackoverflow, 还有以下书籍和帖子,感谢这么多人为这个主题提供了如此丰富完整的答案,使我受益,在此综合各方面的材料立文于此,供后来人查阅,而不至于迷失在那些 Copy + Paste 的博文中。

1. 多线程

注:关于多线程,涉及 Block,GCD 等,内容太多,容后另起一篇展开细说。

1.1 atomic (默认值)

  • atomic 指的是某个时刻只有一个线程(thread)能访问该变量。
  • atomic 是“线程安全”的。
  • 但牺牲了一些性能(可想而知,线程都得排队着来)。
  • atomic 在 非 ARC 下 (也就是手动使用 retain/release/autorelease 做内存管理),需要用 “lock” 机制来确保其他 thread 影响到当前 thread 对变量的读写。
// Example 
@property (retain) NSString *name; 
@property (atomic, retain) NSString *name; // 这两种效果一样,因为 atomic 是默认值。

1.2 nonatomic


  • nonatomic 指的是某个时刻允许有多个线程(thread)能访问该变量。
  • nonatomic“线程安全”的。
  • 性能比 atomic好。
  • 因为不是默认值,所以在大多数情况下都建议显式设为 nonatomic(Big Nerd Ranch 和 Apple 都这么干)。
// Example 
@property (nonatomic, retain) NSString *name;
@synthesize name;

2. 可读/写性(readwrite / readonly)

编译器会为具有 readwrite 的 property 生成 getter 和 setter 方法;为 readonly 的 property 只生成 getter 方法。来段代码:

// Sample

// 1. 声明
@property (nonatomic, readwrite, strong) NSDate *dateModified;
@property (nonatomic, readonly, strong) NSDate *birthday;

// 编译器就会生成的代码
// 2. 变量
NSDate __strong *_dateModified;
NSDate __strong *_birthday;

// 设为 readwrite 的,生成 getter 和 setter
// 3. getter
- (NSDate *) dateModified{
    return _dateModified;

// 4. setter
- (void) setDateModified:(NSDate *)dateModified{
    _dateModified = dateModified;

// 5. 设为 readonly 的,只生成 getter
- (NSDate *) birthday{
    return _birthday;

3. 内存管理特性

这些特性中,最复杂的是内存管理相关的特性,先来看 @property 声明的内存管理相关之 attributes 和编译器生成的变量的 ownership modifiers 的对应关系,然后逐一展开。

Attribute Ownership Modifier Remark
strong __strong 实例变量(instance variables)和局部变量的默认值
retain __strong
weak __weak
unsafe_unretained __unsafe_unretained non-object (或称基础数据类型:int, float 和 NSInteger等) 变量的默认值
assign __unsafe_unretained
copy __strong 所有这些属性中,只有 copy 不是简单的赋值,它是通过 NSCopying 接口的 copyWithZone: 方法复制赋值源所生成的对象。

3.1 strong = retain (iOS4)

  • 意思是说:唉!我拥有那个对象,它要留在堆(heap)里,直到我(和其他 strong 变量)不再指向那个对象,它才能被释放( -> dealloc -> free(object) )。
  • strong 是实例变量(instance variables)和局部变量(也叫“自动变量”,“自动”指的是超出{}作用域后“自动”被释放)的默认值。
  • strong虽然是默认值,但程序员应该显式声明为strong(因为 Apple 曾经修改过默认值,以后可能还会改动)。
  • 在 ARC 下,编译器会在编译阶段(而不是运行时,因为 OC 是“由编译器进行内存管理的语言”)帮你在适当位置插入代码,搞定 strong 变量的 release,不用担心。
// Sample

// 1. 声明
@property (nonatomic, strong) NSObject *obj;

// 编译器就会生成的代码
// 2. 变量
NSObject __strong *_obj;

// 3. getter
- (NSObject *) obj{
    return _obj;
// 4. setter
- (void) setObj:(NSObject *)obj{
     _obj = obj; 

3.2 weak = unsafe_unretained (iOS4)

  • weak 只在 ARC 模式下有效。
  • weak 不拥有指向的对象,也不会 retain 它,不需要 release 它,这行为和 assign 一样。
  • weak 所指向的对象被释放后,这指针就会被设置为 nil。如下表,所有指向 0x100002080 的3个weak 变量都会被设置为 nil。
    NSObject *obj = [[NSObject alloc] init];
    __weak NSObject *obj_1 = obj;
    __weak NSObject *obj_2 = obj;
    __weak NSObject *obj_3 = obj;

weak(类似引用计数表,其实是个 hash 过的散列表,这里为了讲解方便就直接写地址),所有 weak 变量都会被放到这里统一管理。当对象被释放的时候,所有以此对象地址为 Key 的变量都会被找出来,一并设置为 nil。

weak 变量地址
0x100002080 0x00007fff5fbff7c0
0x100002080 0x00007fff5fbff7b8
0x100002080 0x00007fff5fbff7b0
// Sample

// 1. 声明
@property (nonatomic, weak) NSObject *obj; 

// 编译器就会生成的代码
// 2. 变量
NSObject __weak _obj;

// 3. getter
- (NSObject *) obj{
    return _obj;
// 4. setter
- (void) setObj:(NSObject *)obj{
     _obj = obj; 

3.2.1 weak 解决强引用环

设想一下,如果所有对象都是strong 也不行,会产生强引用环(strong reference cycle),强引用环越来越多,就会造成内存溢出。举个栗子(图片来自 Apple), 强引用环

//此时 Person 实例和 Apartment 实例的引用计数(RC: Reference Count)都是 2

john = nil
number73 = nil  //把两个变量(指针)都转向nil

//此时 Person 实例和 Apartment 实例的引用计数都减到 1

强引用环 这时候 Person 实例和 Apartment 实例已经没有外部变量指向他们,只有互相内部的变量指向彼此。由于引用计数不为0,所以这两个对象都不能被系统释放,内存地址也被遗忘(因为原本唯一指向这两个实例的内存地址的 john 和 number73 已经指向 nil),造成内存泄露。

这时候,weak 出现了。weak 的特点就是不会改变“被指向对象”的RC,也就是下图中的 Person 实例的RC是1,因为只有 john 指向他。 强引用环

john = nil  //把变量(指针)转向nil

//此时 Person 实例的RC减到 0,就可以被系统回收了


number73 = nil  //再把这变量(指针)也转向nil

//此时 Apartment 实例的RC也减到 0,同样可以被系统回收了


3.4 unsafe_unretained = assign (没有 ARC 的年代)

  • unsafe_unretained用于非对象属性(non-object),比如基础类型 int, float 等,由于都是被分配在栈(stack)上,栈帧弹出后自动释放,不需刻意做内存管理。
  • unsafe_unretained表示 getter 和 setter 直接为实例变量赋值。Apple 在引入 ARC 前曾经使用 assign 表示这种类型。 ~~~objc @property (nonatomic, unsafe_unretained) float price; // 初学者注意这里不是 *price @property (nonatomic) float price; // 和上面是相等的,因为默认值是 unsafe_unretained。 ~~~

根据 BNR iOS编程(第4版): unsafe_unretained 中的 “unsafe” 可能会误导读者,这个 “unsafe” 是相对于 weak 而言的。与 weak 不同,unsafe_unretained 类型的指针指向的对象被销毁时,指针不会被设置为 nil,而是成为野指针(Dangling Pointer or Wild Pointer),这类指针指向的地址上的对象已经被 destroied,继续读写这个地址已经无意义而且危险(因为你不知道这块内存此时是不是正存放着其他重要的数据)。


3.5 copy

copy 是为了给 setter 方法赋予“复制”对象的能力,而不是直接给人家一个指针。 这个特性通常用于业务逻辑中易被改变的数据类型,比如 NSString 及其子类 NSMutableString, 还有 NSArray 及其子类 NSMutableArray。在某个拥有这些实例的“拥有者”对实例(入参 nickName)修改的时候,不会影响到其他“拥有者”所指向的那些 “nickName” 对象们。 比如以下代码:

// Sample

// 1. 声明
@property (nonatomic, copy) NSString *nickName;

// 2. 变量
NSString __strong *nickName; // 这里是 __strong

// 3. getter
- (NSString *) nickName{
    return _nickName;
// 4. setter
- (void) setNickName:(NSDate *)nickName{
    _nickName = [nickName copy]; // 这里的 copy 会复制出新的 NSString 对象。


开发Android可以用任何主流OS (Windows, Linux 或者 OSX (发音:OS ten)),这些OS上都有相应的 IDE 和 Compilation Env.,但是做 iOS 开发“只能”在 Apple 独有的 OSX 上做,由于 OSX 以及 Mac 电脑的的封闭性和独特性,并不像装 Windows 那样随意买几坨硬件攒台PC就能跑得起来,因为这些硬件在 OSX 上大多都没有相应的驱动(硬件厂家没为 OSX 开发驱动)。

但是,从OSX 10.6 Snow Leopard开始,OSX的所有代码已经完全撇除对 IBM Power 系列 CPU 的支持,转向了 Intel,这就为黑苹果(Hackintosh)的诞生提供了可能性。



  1. CPU:必须 Intel CPU,农企的U会让你很受伤
  2. 主板:技嘉Intel芯片组的主板的安装成功率最高
  3. 显卡:基于1.的选择,如果CPU集成了显卡,通常都可以直接完美驱动;或者干脆买N记的显卡。
  4. 无线网卡: 参照下表


  • Intel 英特尔 Core酷睿 i3-3220 盒装CPU 双核四线程/3.3GHz/3MB三级缓存/LGA1155 该CPU集成的HD2500显卡无法直驱,建议选择其他型号,这便省下了显卡的钱,专心学习,少玩游戏 XD
  • GIGABYTE 技嘉 GA-B75N 主板 Intel B75/LGA1155
  • 昂达(ONDA)GTX650典范1GD5 1058/5000MHz 1G/128bit DDR5显卡
  • 博通BCM4322 双频300M笔记本内置无线网卡 一定记得买一对Wifunni天线,不然接受不到信号。
  • 鼠标键盘 如无必要,尽可能用有线鼠标键盘,直接插机箱后面的USB口)
  • SilverStone 银欣 SST-ST45SF 台式机电源
  • 海盗船(CORSAIR)追击者 DDR3 1600 8GB * 2 台式机内存
  • 希捷(Seagate)1TB ST1000DM003 7200转64M SATA 6Gb/秒 分区后作Windows安装盘和主要数据储存盘用
  • SanDisk 闪迪 至尊高速系列 SDSSDHP-064G-Z25 64G SATA3 SSD固态硬盘 用来装OSX,最多买128G的就够,因为SSD是耗材迟早要报销的,一旦买太大了到时坏了心疼

开始安装 OS X 和 Windows 双系统


  1. 遇到问题就爬论坛找答案,99%的问题在pcbeta都可以找到答案,当然你有梯子更好。
  2. OS X Yosemite 10.10.3 原版镜像下载链接 密码: hvh9,解压后里面那个5G多的.dmg就是真身,TransMac 要用的就是这个。
  3. 坊间公认 Clover 引导比变色龙引导要稳定,也最接近真正的Mac。 附上我本机的EFI分区内容和下载链接 密码: 7dau,里面的配置几乎都没动过,只是在/Volumes/EFI/EFI/CLOVER/kexts/10.10里增加了几个kext。这样的简单配置结果是除了开机和关机会重启几次之外(重启后在 Clover 选择进入哪个 OS 的时候直接按电源键关机吧,以后再想办法解决这个问题),对开发没有影响。
  4. Mac 下怎么显示隐藏的 EFI 分区,并图形化设置 Clover 参数呢?用 Clover Configurator 密码: zk4g


当然,壕要么直接 Mac Pro,要么淘宝一个黑苹果也未尝不可。


图解 SSL/TLS 协议

1. 概览

在构建网络应用,特别是暴露在 internet 中的应用时,通常都会使用 SSL/TLS 协议增强数据传输的安全性,其结构如下: TLS协议结构

2. 握手协议 Shakehand

其中最重要,最复杂(未必是被理解最清楚的)的是握手协议 Shakehand。本来想找一张清晰易懂的 Shakehand 流程图,看到 wikipedia 的这张图很好,有人持续更新它,但就是字体太小,眼睛都瞪瞎了*_*,索性操起超超超强大的需先科学上网,Why?),从新做轮子,期间参考了《图解密码技术》的相关章节,加入了便于理解的对话。希望这图对大家有帮助。

另外,大家可以留意一下 Client 和 Server 证书(cert.)的交换时机(Phase 2 和 3),这就是我们平时在客户端和服务器端所安装的证书的使用时刻,这里是典型的双向证书验证,通常在搭建SSL/TLS应用的时候都这么做,目的是确保双方都是可信的(因为双方都安装了某 CA 的 root cert,且双方的 cert 都由这个 CA所 trust,所 issue)。 握手过程

握手完成后,Client 和 Server 端就会使用应用数据协议和 TLS 记录协议进行加密通信。 从结果来看,握手协议完成了下列操作:

  1. Client 端获得了 Server 端的合法公钥,完成了 Server 认证。
  2. Server 获得了客户端的合法公钥,完成了 Client 认证 (当需要客户端认证时)。
  3. Client 和 Server 生成了消息认证码(MAC:Message Authentication Code)中使用的共享密钥。
  4. Client 和 Server 生成了加密通信中使用的共享密钥(上图的 MS)。

3. 解答几个网上常见的问题:

1. SSL 和 TLS 的区别

TLS 是 SSL 的继承者,SSL3.0,之后的 TLS1.0 相当于 “SSL3.1”。

Version 公布日期 Remark
SSL 1.0 Netscape 未公布
SSL 2.0 1995
SSL 3.0 1996
TLS 1.0 1999 为了兼容SSL,包括可以降级到SSL 3.0的实现,这削弱了连接的安全性
TLS 1.1 2006
TLS 1.2 2008
TLS 1.3 TBD,至Apr 2015 还是草案状态

2. TLS (Transport Layer Security) 是传输层协议吗?


TLS: In the Internet Protocol Suite, TLS and SSL encrypt the data of network connections in the application layer. In OSI model equivalences, TLS/SSL is initialized at layer 5 (session layer) and works at layer 6 (the presentation layer).[citation needed]

它在会话层被初始化,然后工作在表示层。另外,不仅是HTTP,其他应用层协议(例如:FTP, SMTP 等)都可以使用 TLS,而常见的 UDP 使用的是 DTLS

3. SSL 和 TLS,应该选用哪个作为服务器端的安全策略的一部分?

尽量用最新的 TLS 1.2,它修复了之前版本的许多漏洞。当前大部分 WS(Web Server)产品都已经支持,如从NginxTomcat 6.0.43IIS 7.5开始。即使你当前用的WS不支持 TLS 1.2,也尽可能使用支持 TLS 1.0的WS版本,并且禁用 Client 和 Server 端的 SSL 3.0,因为去年底爆出的 POODLE安全缺陷说明仅仅升级到 TLS 1.x是不够的。


  1. 攻击者先通过Version rollback attacks使 TLS shakehand 失败,C/S就会协商降级使用SSL 3.0 再次shakehand。
  2. 然后就可以利用 POODLE 进行攻击啦。

有鉴于此,在 POODLE 缺陷被证实后,主流浏览器大厂已经在自家产品中强制使用 TLS 并禁用了 SSL 3.0,杜绝 rollback 回 SSL 3.0。如果你的浏览器已经禁用 SSL 3.0 的话,浏览只支持 SSL 3.0 的网站会看到类似的警告: Firefox禁用了SSL3.0

4. 怎么知道我用的浏览器和某网站支持什么版本的 SSL/TLS 协议?


nmap --script ssl-enum-ciphers -p 443
Starting Nmap 6.40 ( ) at 2015-05-05 08:36 HKT
Nmap scan report for (
Host is up (0.091s latency).
DNS record for
443/tcp open  https
| ssl-enum-ciphers: 
|   SSLv3: 
|     ciphers: 
|       TLS_RSA_WITH_AES_128_CBC_SHA - strong
|       TLS_RSA_WITH_AES_256_CBC_SHA - strong
|       TLS_RSA_WITH_RC4_128_SHA - strong
|     compressors: 
|       NULL
|   TLSv1.2: 
|     ciphers: 
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - strong
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - strong
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - strong
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - strong
|       TLS_RSA_WITH_AES_128_CBC_SHA - strong
|       TLS_RSA_WITH_AES_128_CBC_SHA256 - strong
|       TLS_RSA_WITH_AES_128_GCM_SHA256 - strong
|       TLS_RSA_WITH_AES_256_CBC_SHA - strong
|       TLS_RSA_WITH_AES_256_CBC_SHA256 - strong
|       TLS_RSA_WITH_AES_256_GCM_SHA384 - strong
|       TLS_RSA_WITH_RC4_128_SHA - strong
|     compressors: 
|       NULL
|_  least strength: strong
Nmap done: 1 IP address (1 host up) scanned in 3.82 seconds

5. 为什么连 这样的网站还保留 SSL 3.0?不是说 SSL3.0 不安全了吗?

问得好!它不但保留了 SSL 3.0,还保留了已经不安全的 RC4 加密算法(速度极快的算法,8bit 的机器都能很快算出伪随机数(图上的 RNc))。

这不是阿里的疏忽,而是像许多网站那样想兼容那些旧版浏览器(虽然的数量已经很少很少),比如像我 XP 里那万年不升级的 IE6 和老旧的功能手机 Candy bar phone的内置浏览器。