2

我正在构建一个接受付款的移动应用程序。用户输入他们的 CC 详细信息,付款信息通过 HTTPS 提交到零售商的 POS 系统。POS 直接处理付款并需要实际的信用卡信息才能工作,因此我们不能使用像 Stripe 这样的服务来存储卡,并给我们一个令牌来处理付款。

由于应用程序的性质,用户将定期付款,因此我想存储他们的 CC 信息以方便使用。但是,这不是定期计费,用户将随意发起交易。因此,我不需要将 CC 集中保存在服务器上,我正在考虑使用这种方法在每个用户的设备上存储单独的卡:

  • 收集 CC 编号和到期日期
  • 使用 AES256 加密,使用 CVC 作为密钥(CVC 未存储)
  • 然后将加密的数据存储在 iOS 钥匙串中(或等效于 Android)
  • 为了进行支付,(a) 从钥匙串中取出数据,并且
  • (b) 用户必须输入 CVC 才能解密 CC 信息

这个想法是,如果用户知道 CVC,他们可能无论如何都拥有该卡,因此他们不需要尝试破解设备。

对于加密,我正在考虑使用RNCryptor lib。它的主要功能之一是将常用密码自动转换为两个 256 位密钥的加密“随机”字节序列,用于加密和身份验证。密钥拉伸是通过 10k 轮 PBKDF2 实现的。实现细节在链接中,但简而言之:

  • AES-256 加密
  • CBC模式
  • 使用 PBKDF2 进行密码拉伸
  • 密码加盐
  • 随机四
  • 加密然后散列 HMAC


问题:

我对数学的理解还不够好,无法判断仅用 3 个 CVC 数字播种 RNCryptor 的密钥拉伸实现是否会产生统计上足够随机的密钥。我无法找到任何有关 RNCryptor 保持安全所需的密码规范的文档。对此的任何想法将不胜感激。使用这个库就像这样简单:

// Encryption
NSData *data = ...
NSString *password = @"Secret password";
NSData *ciphertext = [RNCryptor encryptData:data password:password];

// Decryption
NSError *error = nil;
NSData *plaintext = [RNCryptor decryptData:ciphertext password:password error:&error];
if (error != nil) {
    NSLog(@"ERROR:%@", error);
    return
}
// ...

在 iOS 钥匙串(或 droid 等效项)上讲述AES256 加密的CC 信息时,是否启用设备锁定密码是否重要?我的想法是,信息已经是 AES256 加密的,它可以存储在设备上而无需钥匙串的加密吗?

鉴于没有存储大量 CC 编号的中央服务器,在这种情况下,PCI 合规性的哪些部分是相关的?我尝试阅读 PCI 规范,但文档是一个迷宫:(

4

2 回答 2

3
  1. 正如 Ebbe 指出的那样,仅使用 CVC 作为密钥,即使使用 PBKDF2 从 CVC 派生也不安全,只有 1000 个可能的密钥。密钥中必须包含其他内容。

  2. 日期充当部分婴儿床,因为它具有已知的格式和有限的值。还要注意不要包括任何其他婴儿床,例如田间分隔符或田间指示器。

  3. 信用卡帐号验证校验位也是婴儿床。

  4. 为了使钥匙串安全,用户必须输入设备锁定密码。

  5. 必须避免越狱和 root 设备,这很难确定。

  6. 只要只保存 CC# 和到期日期,而不是任何磁道 2 数据,并且按照 PCI 标准加密,就可以了。

  7. 请参阅 PCI点对点加密标准,它在 PCI 站点上是免费的。请参阅表 2,应用程序开发人员。

  8. 最后让 PCI 审核员审查您的计划,这只是提供信息的“最佳信息”,没有经过全面评估。

根据 OP 的评论更新:

有 1000 个 CVC 可供尝试。RNCryptor 每次 CVC 尝试将花费约 200 毫秒,这意味着可以在约 4 分钟内尝试所有 1000 次——哎呀。RNCryptor 具有身份验证功能,因此在尝试正确的 CVC 时会立即知道。这至少不安全,并且身份验证对您不利。

如果没有身份验证,则需要依赖婴儿床。第一个婴儿床是校验位,它将排除约 900 个 CVC,剩下 100 个。

但实际上情况更糟,具体取决于加密的格式。使用不正确的密钥解密将返回基本上随机的字节。如果 CC# 和日期是字符串,则结果是数字字符串的几率实际上是压缩的,因此将立即知道正确的解密。最好的办法是将 CC# 转换为大整数,将日期转换为数字日+年并对其进行加密。但即便如此,仍有校验位婴儿床和用于验证解密的有效日期。实际上,在加密中不包括到期日期更安全。

最后使用 CVC 作为密钥是不安全的,需要更长的密钥。

钥匙串不会保护其内容免受设备所有者的侵害,实际上设备所有者就是有权访问的人,密码是确定访问权限的对象,因此是设备所有者。

于 2017-04-13T23:18:19.593 回答
0

如果您不想自己实现所有的东西,您可以查看适用于 iOS 和 Android 的 VGSCollect SDK。SDK 收集 PCI 范围内的所有数据。所有加密人员都在他们身边完成,因此您只需获得可在发送付款请求时使用的别名。

于 2020-01-29T12:46:28.640 回答