跳转至

Cryptographic Vulnerability: Insecure Algorithm

密码学漏洞:不安全的算法

描述

在密码学中,密码(cipher)是执行加密或解密的算法—— 一系列可以作为程序遵循的明确步骤。

通常有两个系列:

  • 块密码 (Block Cipher):块密码在将明文消息转换为 密文。
  • 流密码 (Stream Cipher):另一方面,流密码将明文消息分解为单个位,然后 使用密钥位将它们逐个转换为密文。

常见的加密算法:

  • DESTriple DES:Triple DES旨在取代最初的数据加密标准(DES)算法, 黑客最终学会了相对容易地攻破它。曾经,Triple DES是推荐的标准, 并且是业界最广泛使用的对称算法。Triple DES使用三个各自为56位的独立密钥。 总密钥长度加起来为168位,但专家认为112位的密钥强度更为准确。 尽管正在逐渐被淘汰,Triple DES 在很大程度上已被高级加密 标准(AES)所取代。
  • AES:高级加密标准(AES)是被美国政府信任为标准的算法,并且 众多组织信任。虽然128位形式的效率非常高,AES还使用192位和256位的密钥 用于高强度的加密目的。AES在很大程度上被认为对所有攻击都是无懈可击的,除了暴力破解(它 尝试使用128、192或256位密码中的所有可能组合来解密消息。)
  • RSA:RSA是一种公钥加密算法,也是加密在互联网上发送的数据的标准。它还 是PGP和GPG程序中使用的方法之一。与Triple DES不同,RSA被认为是一种非对称 算法,因为它使用一对密钥。您拥有用于加密消息的公钥和用于 解密它。RSA 加密的结果是一大堆乱码,攻击者需要花费大量时间和 处理能力才能破解。
  • ECC:椭圆曲线密码学(ECC)是一种基于密钥的数据加密技术。ECC专注于公开密钥对 以及用于解密和加密网络流量的私钥。ECC在 Rivest–Shamir–Adleman (RSA) 加密算法的背景下被频繁讨论。RSA可以 使用素因数分解实现对电子邮件、数据和软件等的单向加密。

DESTriple DES是不安全的,绝不能使用。其他算法由于不安全的 密码模式设置、密钥大小或特殊密钥情况所导致的一些弱点。

import 'dart:convert';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:crypto/crypto.dart';
import 'package:pointycastle/export.dart' as pc;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Insecure Encryption Demo'),
        ),
        body: EncryptionWidget(),
      ),
    );
  }
}

class EncryptionWidget extends StatefulWidget {
  @override
  _EncryptionWidgetState createState() => _EncryptionWidgetState();
}

class _EncryptionWidgetState extends State<EncryptionWidget> {
  final _controller = TextEditingController();
  String _encryptedText = '';

  void _encryptText() {
    final key = utf8.encode('insecurekey');
    final iv = Uint8List(8);
    final s = pc.SICStreamCipher(pc.DESEngine())
      ..init(true, pc.ParametersWithIV(pc.KeyParameter(key), iv));
    final input = utf8.encode(_controller.text);
    final output = s.process(input);
    setState(() {
      _encryptedText = base64.encode(output);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        TextField(
          controller: _controller,
          decoration: InputDecoration(
            labelText: 'Enter text to encrypt',
          ),
        ),
        RaisedButton(
          onPressed: _encryptText,
          child: Text('Encrypt'),
        ),
        Text('Encrypted text: $_encryptedText'),
      ],
    );
  }
}
import Foundation
import CommonCrypto

func DES_Encrypt(input: String, key: String) -> String {
    let data = input.data(using: String.Encoding.utf8)!
    let keyData = key.data(using: String.Encoding.utf8)!
    let keyBytes = keyData.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) -> UnsafePointer<UInt8> in
        return bytes
    }
    let dataLength = Int(data.count)
    let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: dataLength + kCCBlockSizeDES)
    let bufferPtr = UnsafeMutableRawPointer(buffer)
    let bufferPtrBytes = bufferPtr.bindMemory(to: Void.self, capacity: dataLength)
    let iv = [UInt8](repeating: 0, count: kCCBlockSizeDES)
    var numBytesEncrypted :size_t = 0
    let cryptStatus = CCCrypt(CCOperation(kCCEncrypt), CCAlgorithm(kCCAlgorithmDES), CCOptions(kCCOptionPKCS7Padding), keyBytes, kCCKeySizeDES, iv, data.bytes, dataLength, bufferPtrBytes, dataLength + kCCBlockSizeDES, &numBytesEncrypted)
    if UInt32(cryptStatus) == UInt32(kCCSuccess) {
        let encryptedData = Data(bytes: UnsafePointer<UInt8>(buffer), count: numBytesEncrypted)
        buffer.deallocate()
        return encryptedData.base64EncodedString()
    } else {
        buffer.deallocate()
        return ""
    }
}

func main() {
    print("Enter text to encrypt:")
    let input = readLine() ?? ""
    print("Enter encryption key:")
    let key = readLine() ?? ""
    let encrypted = DES_Encrypt(input: input, key: key)
    print("Encrypted text: \(encrypted)")
}

main()
import javax.crypto.Cipher
import javax.crypto.SecretKey
import javax.crypto.SecretKeyFactory
import javax.crypto.spec.DESKeySpec
import java.util.*

fun main(args: Array<String>) {
    val scanner = Scanner(System.`in`)
    println("Enter text to encrypt:")
    val text = scanner.nextLine()
    println("Enter DES key:")
    val key = scanner.nextLine()

    val encryptedText = encrypt(text, key)
    println("Encrypted text: $encryptedText")

    val decryptedText = decrypt(encryptedText, key)
    println("Decrypted text: $decryptedText")
}

fun encrypt(text: String, key: String): String {
    val desKey = SecretKeyFactory.getInstance("DES").generateSecret(DESKeySpec(key.toByteArray()))
    val cipher = Cipher.getInstance("DES")
    cipher.init(Cipher.ENCRYPT_MODE, desKey)
    return Base64.getEncoder().encodeToString(cipher.doFinal(text.toByteArray()))
}

fun decrypt(text: String, key: String): String {
    val desKey = SecretKeyFactory.getInstance("DES").generateSecret(DESKeySpec(key.toByteArray()))
    val cipher = Cipher.getInstance("DES")
    cipher.init(Cipher.DECRYPT_MODE, desKey)
    return String(cipher.doFinal(Base64.getDecoder().decode(text)))
}

建议

对于安全可靠的加密,至关重要的是使用经过广泛审查并被行业广泛采用的现代且强大的加密算法。对于不安全的DES和Triple DES,两个推荐的替代方案是高级加密标准(AES)和椭圆曲线密码学(ECC)。

AES 被广泛认为是一种高效且安全的对称加密算法。它提供 128、192 和 256 位的密钥长度,使其适用于各种加密目的。事实证明,AES 能够抵抗大多数已知攻击,使其成为数据保护的绝佳选择。

另一方面,ECC 是一种非对称加密技术,使用一对公钥和私钥进行加密和解密。与 RSA 等其他非对称算法相比,ECC 以使用更短的密钥长度提供更强的安全性而闻名。这会在保持高安全级别的同时加快加密和解密过程。

为了在使用任何加密算法时确保最高程度的安全性,遵循最佳实践至关重要:

  • 密钥长度:使用被认为安全的密钥长度。对于 AES,128 位足以满足大多数用例,但对于更敏感的数据,您可以选择 192 或 256 位。

  • 加密模式:始终采用安全的密码模式设置,如带有适当填充的AES-GCM(Galois/Counter Mode)或AES-CBC(Cipher Block Chaining)。

  • 密钥管理:使用安全存储机制(对于 Android 是 Keystore,对于 iOS 是 Keychain)来安全地存储加密密钥。

import 'dart:convert';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:pointycastle/export.dart' as pc;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Secure Encryption Demo'),
        ),
        body: EncryptionWidget(),
      ),
    );
  }
}

class EncryptionWidget extends StatefulWidget {
  @override
  _EncryptionWidgetState createState() => _EncryptionWidgetState();
}

class _EncryptionWidgetState extends State<EncryptionWidget> {
  final _controller = TextEditingController();
  String _encryptedText = '';

  void _encryptText() {
    final key = pc.KeyParameter(Uint8List.fromList(utf8.encode('securekey123456789012345678901234'))); // 32 bytes for AES-256
    final iv = Uint8List(12); // 12 bytes for GCM IV
    final cipher = pc.GCMBlockCipher(pc.AESFastEngine())
      ..init(true, pc.AEADParameters(key, 128, iv));
    final input = utf8.encode(_controller.text);
    final output = cipher.process(Uint8List.fromList(input));
    setState(() {
      _encryptedText = base64.encode(output);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        TextField(
          controller: _controller,
          decoration: InputDecoration(
            labelText: 'Enter text to encrypt',
          ),
        ),
        RaisedButton(
          onPressed: _encryptText,
          child: Text('Encrypt'),
        ),
        Text('Encrypted text: $_encryptedText'),
      ],
    );
  }
}
import Foundation
import CryptoKit

func AES_GCM_Encrypt(input: String, key: String) -> String {
    guard let data = input.data(using: .utf8),
          let keyData = key.data(using: .utf8) else {
        return ""
    }

    let iv = Data(count: AES.GCM.nonceSize)

    do {
        let sealedData = try! AES.GCM.seal(plainData!, using: key, nonce: AES.GCM.Nonce(data:nonce!))
        let encryptedContent = try! sealedData.combined!
        return sealedData.ciphertext.base64EncodedString()
    } catch {
        return ""
    }
}

print("Enter text to encrypt:")
if let input = readLine() {
    print("Enter encryption key:")
    if let key = readLine() {
        let encrypted = AES_GCM_Encrypt(input: input, key: key)
        print("Encrypted text: \(encrypted)")
    }
}
import java.security.SecureRandom
import javax.crypto.Cipher
import javax.crypto.SecretKey
import javax.crypto.SecretKeyFactory
import javax.crypto.spec.GCMParameterSpec
import javax.crypto.spec.PBEKeySpec
import javax.crypto.spec.SecretKeySpec
import java.security.spec.KeySpec
import java.util.*

fun main(args: Array<String>) {
    val scanner = Scanner(System.`in`)
    println("Enter text to encrypt:")
    val text = scanner.nextLine()
    println("Enter AES key:")
    val key = scanner.nextLine()

    val salt = ByteArray(16)
    SecureRandom().nextBytes(salt)
    val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")
    val spec: KeySpec = PBEKeySpec(key.toCharArray(), salt, 65536, 256)
    val secretKey = factory.generateSecret(spec)
    val secretKeySpec = SecretKeySpec(secretKey.encoded, "AES")

    val encryptedText = encrypt(text, secretKeySpec)
    println("Encrypted text: $encryptedText")

    val decryptedText = decrypt(encryptedText, secretKeySpec)
    println("Decrypted text: $decryptedText")
}

fun encrypt(text: String, key: SecretKey): String {
    val cipher = Cipher.getInstance("AES/GCM/NoPadding")
    val iv = ByteArray(12)
    SecureRandom().nextBytes(iv)
    val gcmSpec = GCMParameterSpec(128, iv)
    cipher.init(Cipher.ENCRYPT_MODE, key, gcmSpec)
    val encryptedBytes = cipher.doFinal(text.toByteArray())
    val encryptedTextAndIV = ByteArray(iv.size + encryptedBytes.size)
    System.arraycopy(iv, 0, encryptedTextAndIV, 0, iv.size)
    System.arraycopy(encryptedBytes, 0, encryptedTextAndIV, iv.size, encryptedBytes.size)
    return Base64.getEncoder().encodeToString(encryptedTextAndIV)
}

fun decrypt(text: String, key: SecretKey): String {
    val cipher = Cipher.getInstance("AES/GCM/NoPadding")
    val decodedText = Base64.getDecoder().decode(text)
    val iv = decodedText.copyOfRange(0, 12)
    val encryptedBytes = decodedText.copyOfRange(12, decodedText.size)
    val gcmSpec = GCMParameterSpec(128, iv)
    cipher.init(Cipher.DECRYPT_MODE, key, gcmSpec)
    return String(cipher.doFinal(encryptedBytes))
}

链接

标准

  • OWASP_MASVS_L1:
    • MSTG_CRYPTO_2
    • MSTG_CRYPTO_3
    • MSTG_CRYPTO_4
  • OWASP_MASVS_L2:
    • MSTG_CRYPTO_2
    • MSTG_CRYPTO_3
    • MSTG_CRYPTO_4
  • PCI_STANDARDS:
    • REQ_3_6
    • REQ_3_7
    • REQ_4_2
    • REQ_6_2
  • OWASP_MASVS_v2_1:
    • MASVS_CRYPTO_1
    • MASVS_CRYPTO_2
  • SOC2_CONTROLS:
    • CC_2_1
    • CC_4_1
    • CC_6_7
    • CC_7_1
    • CC_7_2
    • CC_7_4
    • CC_7_5
  • CNIL_FOR_DEVELOPERS:
    • DEVELOPERS_4_1_4
  • HIPAA_CONTROLS:
    • SECURITY252
    • SECURITY212
    • SECURITY213