Cryptographic Vulnerability: Insecure Algorithm
Vulnérabilité cryptographique : Algorithme non sécurisé
Description
En cryptographie, un chiffrement (ou chiffre) est un algorithme permettant d'effectuer le chiffrement ou le déchiffrement — une série d' étapes qui peuvent être suivies comme une procédure.
Il existe généralement deux familles :
- Blocker Cipher (Chiffrement par blocs) : Un chiffrement par blocs décompose les messages en texte clair en blocs de taille fixe avant de les convertir en texte chiffré à l'aide d'une clé.
- Stream Cipher (Chiffrement par flux) : Un chiffrement par flux, en revanche, décompose un message en texte clair en bits individuels, qui sont ensuite convertis individuellement en texte chiffré en utilisant des bits de clé.
Algorithmes de chiffrement courants :
DESetTriple DES: Le Triple DES a été conçu pour remplacer l'algorithme original du Data Encryption Standard (DES), que les pirates ont finalement appris à contourner avec une relative facilité. À une époque, Triple DES était le standard recommandé et l'algorithme symétrique le plus utilisé dans l'industrie. Triple DES utilise trois clés individuelles de 56 bits chacune. La longueur totale de la clé s'élève à 168 bits, mais les experts soutiendraient qu'une force de clé de 112 bits est plus précise. Bien qu'il soit progressivement abandonné, le Triple DES a été en grande partie remplacé par l'Advanced Encryption Standard (AES).AES: L'Advanced Encryption Standard (AES) est l'algorithme reconnu comme standard par le gouvernement américain et de nombreuses organisations. Bien qu'il soit très efficace sous sa forme de 128 bits, l'AES utilise également des clés de 192 et 256 bits à des fins de chiffrement intensif. L'AES est largement considéré comme invulnérable à toutes les attaques, à l'exception de la force brute, qui tente de déchiffrer des messages en utilisant toutes les combinaisons possibles dans le code à 128, 192 ou 256 bits.RSA: RSA est un algorithme de chiffrement à clé publique et la norme pour chiffrer les données envoyées sur Internet. C'est également également l'une des méthodes utilisées dans les programmes PGP et GPG. Contrairement à Triple DES, le RSA est considéré comme un algorithme asymétrique en raison de son utilisation d'une paire de clés. Vous avez votre clé publique pour chiffrer le message et une clé privée pour le déchiffrer. Le résultat du chiffrement RSA est un énorme lot de charabia qui nécessite beaucoup de temps et de puissance de traitement à briser.ECC: L'Elliptic Curve Cryptography (ECC) est une technique basée sur des clés pour chiffrer des données. L'ECC se concentre sur des paires de clés publiques et privées pour le déchiffrement et le chiffrement du trafic web. L'ECC est fréquemment abordée dans le contexte de l' l'algorithme cryptographique Rivest–Shamir–Adleman (RSA). RSA permet un chiffrement unidirectionnel de choses telles que les e-mails, les données et les logiciels utilisant la factorisation en nombres premiers.
DES, Triple DES ne sont pas sécurisés et ne doivent pas être utilisés. D'autres algorithmes souffrent de certaines faiblesses causées par des paramètres de mode de chiffrement
non sécurisés, de la taille de la clé ou de cas de clés spéciaux.
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)))
}
Recommandation
Pour un chiffrement sécurisé et fiable, il est crucial d'utiliser des algorithmes cryptographiques modernes et robustes qui ont fait l'objet d'un examen approfondi et sont largement adoptés par l'industrie. Deux alternatives recommandées aux algorithmes non sécurisés DES et Triple DES sont l'Advanced Encryption Standard (AES) et l'Elliptic Curve Cryptography (ECC).
L'AES est largement reconnu comme un algorithme de chiffrement symétrique hautement efficace et sécurisé. Il offre des longueurs de clé de 128, 192 et 256 bits, ce qui le rend approprié pour divers besoins de chiffrement. L'AES s'est avéré résistant à la plupart des attaques connues, ce qui en fait un excellent choix pour la protection des données.
L'ECC, en revanche, est une technique de chiffrement asymétrique qui utilise des paires de clés publiques et privées pour le chiffrement et le déchiffrement. L'ECC est reconnue pour fournir une sécurité forte avec des longueurs de clé plus courtes comparée à d'autres algorithmes asymétriques comme RSA. Cela permet des processus de chiffrement et de déchiffrement plus rapides tout en maintenant un niveau élevé de sécurité.
Pour garantir une sécurité maximale lors de l'utilisation de tout algorithme cryptographique, il est essentiel de suivre les meilleures pratiques :
-
Longueur de clé : Utilisez des longueurs de clé considérées comme sécurisées. Pour AES, 128 bits sont suffisants pour la plupart des cas d'utilisation, mais vous pouvez opter pour 192 ou 256 bits pour des données plus sensibles.
-
Mode de chiffrement : Utilisez toujours des paramètres de mode de chiffrement sécurisés, tels que AES-GCM (Galois/Counter Mode) ou AES-CBC (Cipher Block Chaining) avec un remplissage (padding) approprié.
-
Gestion des clés : Utilisez des mécanismes de stockage sécurisés (Keystore pour Android, Keychain pour iOS) pour stocker en toute sécurité les clés cryptographiques.
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))
}
Liens
Normes
- 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