2017-04-13 46 views
1

我正在构建一个接受付款的移动应用程序。用户输入他们的CC详细信息,付款信息通过HTTPS提交给零售商的POS系统。 POS直接处理付款并需要实际的信用卡信息才能正常工作,因此我们不能使用存储卡的Stripe等服务,并且给我们返回一个令牌来处理付款。如何以符合PCI标准的方式在iOS/Android上存储信用卡信息

由于应用程序的性质,用户将定期付款,所以我想存储他们的CC信息以方便。然而,这不是反复计费,用户将会随意启动交易。因此,我并不需要一台服务器上集中保持CC和我正在考虑使用这种方法每个用户的设备上存储个人卡:

  • 收集CC数&有效期限采用AES256它
  • 加密,使用在CVC作为密钥(CVC不存储)
  • 然后存储在IOS钥匙串加密的数据(或等效于Android)
  • 要进行付款,(a)中的数据被取出钥匙链的,和
  • (二)用户必须输入CVC才能解密CC信息

这个想法是,如果用户知道CVC他们可能拥有该卡,因此他们不需要尝试黑客入侵设备。

对于加密,我正在考虑使用RNCryptor lib。其主要功能之一是将通用密码自动转换为两个256位密钥的加密“随机”字节序列,以进行加密和认证。关键延伸是通过10k轮PBKDF2实现的。实施细节为中的链接,但在短:

  • AES-256加密
  • CBC模式
  • 密码与PBKDF2拉伸
  • 密码腌制
  • 随机IV
  • 加密,然后-hash HMAC


问题:

我不明白这个数学 - 足以判断用3个CVC数字播种RNCryptor的密钥伸展实现是否会产生足够的统计随机密钥。我一直无法找到有关RNCryptor保持安全所需的密码规格的文档。任何想法,将不胜感激。使用这个LIB是这样简单:

// 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 
} 
// ... 

当storying的AES256在iOS钥匙扣(或DROID当量)加密 CC的信息,这很重要,如果没有设备锁密码启用?我的想法是,信息已经AES256加密,它可以存储在设备上,无需使用钥匙串加密?

鉴于没有中央服务器存储大量CC号码,在这种情况下哪些PCI合规性部分相关?我试着读了PCI规格,但该文档是一个迷宫导航:(

+0

至少您需要验证iDevice是否启用了密码。 – zaph

+0

Aes256需要一个256位密钥,但一个cvc代码只包含10位信息。如果使用cvc代码作为关键字,暴力破解不仅会立即破解,而且还会泄露进程中的cvc代码。 –

+0

这不是ApplePay用于iOS的一方吗? – Bobson

回答

3
  1. 由于Ebbe指出只用CVC作为重点,甚至从PBKDF2的CVC衍生不安全,只有1000可能的钥匙其他必须包含在钥匙中

  2. 由于它具有已知的格式和有限的数值,所以日期可以作为部分婴儿床使用还要注意不要包括任何其他婴儿床,如现场分隔符或现场指示器

  3. 信用卡帐号验证校验码也是一张婴儿床

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

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

  6. 只要保存CC#和截止日期,而不是任何跟踪2数据,并且它被加密到PCI标准,您应该没问题。

  7. 查看PCI Point to Point Encryption Standard,它在PCI站点上是免费的。请参阅表2 Application Developer。

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

更新基础上的OP的评论:

有1000点式CVC尝试。 RNCryptor每次CVC尝试需要大约200毫秒,这意味着所有1000可以在大约4分钟内完成尝试。 RNCryptor具有身份验证功能,因此可以在尝试正确的CVC时立即得知它。这并非不安全,身份验证对您不利。

如果没有身份验证,那么需要依靠婴儿床。第一个婴儿床是校验位,这将排除约900个CVC离开100.

但是是真的更糟,具体取决于加密的格式。使用不正确的密钥解密将返回基本上随机的字节。如果CC#和日期是一个字符串,结果是一个数字字符串的几率实际上就是zip,所以再次正确的解密将被立即知道。最好的选择是将CC#转换为大整数,将日期转换为数字日期+年份并对其进行加密。但即使如此,仍然有校验数字婴儿床和有效的日期来验证解密。实际上,在加密中不包括到期日期会更安全。

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

钥匙串不保护其设备所有者的内容,设备所有者实际上是谁拥有访问权限,密码是确定的访问权限,因此是设备所有者。

+0

谢谢@ zaph,您的评论帮助我更新了我的问题,并提供了一些缺失的细节。我使用RNCryptor从3个CVC数字中创建一个'好钥匙'。我的理解是,这个库执行10k轮PBKDF2伸展,产生两个统计随机字节的256位密钥。但是我不明白数学的好坏 - 足以判断用3位数字播种RNCryptor是否足够安全。对此有何想法?关于iOS钥匙串,如果没有设备锁密码(因为敏感信息已经被AES256加密)是否重要?避免婴儿床上的大提示!谢谢! – DTs

+0

查看答案更新。 – zaph

+0

好的,所以试图在实践中突破这个问题就可以这样工作吗? (a)用户无法使用(或使用已知的)密码访问设备,(b)越狱设备,(c)以编程方式从钥匙串中提取加密的数据,(d)试图暴力破解自己机器上的密码?在这种情况下,关键拉伸是无关紧要的?如果我使用静态长字符串(用户不可见地)改变CVC,然后在解密过程中使用相同的突变,那么该怎么办?然后有人会不得不对我的代码进行反向工程,以确定是否有一个关键的丰富和它的机制。例如: – DTs

相关问题