← Назад к вопросам
Как обращаться к криптографическому сервису чтобы бизнес-логика знала как можно меньше о процессе шифрования?
1.0 Junior🔥 151 комментариев
#Soft Skills и рабочие процессы
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Принцип Dependency Inversion и инкапсуляция
Для изоляции бизнес-логики от деталей криптографии нужно применить принцип инверсии зависимостей (Dependency Inversion Principle). Вместо того чтобы бизнес-логика знала о конкретной реализации шифрования, мы создаём абстрактный интерфейс криптографического сервиса.
Архитектурный подход
Вы должны определить интерфейс криптографического сервиса на уровне бизнес-логики (domain layer), а конкретная реализация будет находиться на уровне инфраструктуры.
// domain/services/CryptoService.interface.ts
export interface ICryptoService {
encrypt(data: string): Promise<string>;
decrypt(encryptedData: string): Promise<string>;
hash(data: string): Promise<string>;
}
// application/usecases/UserRegistration.ts
export class RegisterUserUseCase {
constructor(private cryptoService: ICryptoService) {}
async execute(email: string, password: string): Promise<void> {
// Бизнес-логика не знает ничего о том, как работает шифрование
const hashedPassword = await this.cryptoService.hash(password);
// ... сохраняем пользователя
}
}
Конкретная реализация
Криптографический сервис реализуется на уровне инфраструктуры, полностью скрытый от бизнес-логики:
// infrastructure/services/CryptoServiceImpl.ts
import crypto from "crypto";
import { ICryptoService } from "@/domain/services/CryptoService.interface";
export class CryptoServiceImpl implements ICryptoService {
private encryptionKey = process.env.ENCRYPTION_KEY!;
async encrypt(data: string): Promise<string> {
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv(
"aes-256-cbc",
Buffer.from(this.encryptionKey),
iv
);
let encrypted = cipher.update(data, "utf8", "hex");
encrypted += cipher.final("hex");
return iv.toString("hex") + ":" + encrypted;
}
async decrypt(encryptedData: string): Promise<string> {
const [ivHex, encrypted] = encryptedData.split(":");
const iv = Buffer.from(ivHex, "hex");
const decipher = crypto.createDecipheriv(
"aes-256-cbc",
Buffer.from(this.encryptionKey),
iv
);
let decrypted = decipher.update(encrypted, "hex", "utf8");
decrypted += decipher.final("utf8");
return decrypted;
}
async hash(data: string): Promise<string> {
return crypto.createHash("sha256").update(data).digest("hex");
}
}
Инъекция зависимостей
Когда вы создаёте бизнес-логику, вы передаёте реализацию через конструктор:
// presentation/controllers/AuthController.ts
export class AuthController {
private registerUseCase: RegisterUserUseCase;
constructor(cryptoService: ICryptoService) {
this.registerUseCase = new RegisterUserUseCase(cryptoService);
}
async register(email: string, password: string) {
await this.registerUseCase.execute(email, password);
}
}
Тестирование
Использование интерфейса позволяет легко мокировать криптографический сервис в тестах:
// tests/usecases/UserRegistration.test.ts
const mockCryptoService: ICryptoService = {
encrypt: jest.fn(),
decrypt: jest.fn(),
hash: jest.fn().mockResolvedValue("hashed-password")
};
const useCase = new RegisterUserUseCase(mockCryptoService);
await useCase.execute("user@example.com", "password");
expect(mockCryptoService.hash).toHaveBeenCalledWith("password");
Ключевые преимущества
- Слабая связанность: бизнес-логика независима от реализации
- Простота тестирования: можно использовать мок-объекты
- Гибкость: легко заменить реализацию без изменения бизнес-логики
- Читаемость: код в use case понятен и сосредоточен на логике