Secure Your Full-Stack Applications with Encryption Best Practices
Handling sensitive data is a critical requirement in modern applications. Whether it is user passwords, payment information, personal identification data, or health records, proper encryption ensures data confidentiality and integrity. Combining Angular frontend with ASP.NET Core backend and SQL Server requires careful handling of data both in transit and at rest.
1. Understanding Data Security Layers
Encryption can be implemented at multiple layers:
| Layer | Purpose | Example Techniques |
|---|
| In Transit | Protect data while moving between frontend/backend | HTTPS (TLS), Secure WebSocket (WSS) |
| At Rest | Protect stored data in a database or storage | TDE, Column-level encryption, AES encryption |
| Application Layer | Protect sensitive fields before database insertion | AES, RSA encryption in .NET |
Best practice: Combine in-transit encryption (HTTPS) with application-layer encryption for highly sensitive fields.
2. Encrypting Data in Angular (Frontend)
Angular typically handles data before sending it to the backend. While HTTPS encrypts data in transit, some regulations require end-to-end encryption, where sensitive fields are encrypted in the browser.
Using AES Encryption in Angular
We can use the CryptoJS library for AES encryption.
npm install crypto-js
// encryption.service.tsimport { Injectable } from '@angular/core';
import * as CryptoJS from 'crypto-js';
@Injectable({ providedIn: 'root' })
export class EncryptionService {
private key = 'YOUR_SECURE_KEY'; // Use environment variable in production
encrypt(text: string): string {
return CryptoJS.AES.encrypt(text, this.key).toString();
}
decrypt(cipherText: string): string {
const bytes = CryptoJS.AES.decrypt(cipherText, this.key);
return bytes.toString(CryptoJS.enc.Utf8);
}
}
Example Usage in Component
import { Component } from '@angular/core';
import { EncryptionService } from '../services/encryption.service';
@Component({
selector: 'app-secure-form',
templateUrl: './secure-form.component.html'
})
export class SecureFormComponent {
password: string = '';
constructor(private encryptionService: EncryptionService) {}
submitForm() {
const encryptedPassword = this.encryptionService.encrypt(this.password);
// send encryptedPassword to backend via API
}
}
Frontend Best Practices:
Never store encryption keys in code, use environment variables or a secure key exchange mechanism.
Use AES-256 or higher.
Combine with HTTPS to prevent MITM attacks.
3. ASP.NET Core Backend Encryption
Backend encryption is critical for storing sensitive fields in the database.
Encrypting Fields Using AES
using System.Security.Cryptography;
using System.Text;
public class CryptoService
{
private readonly byte[] _key;
private readonly byte[] _iv;
public CryptoService(IConfiguration config)
{
_key = Encoding.UTF8.GetBytes(config["Encryption:Key"]);
_iv = Encoding.UTF8.GetBytes(config["Encryption:IV"]);
}
public string Encrypt(string plainText)
{
using var aes = Aes.Create();
aes.Key = _key;
aes.IV = _iv;
var encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
var plainBytes = Encoding.UTF8.GetBytes(plainText);
var encryptedBytes = encryptor.TransformFinalBlock(plainBytes, 0, plainBytes.Length);
return Convert.ToBase64String(encryptedBytes);
}
public string Decrypt(string cipherText)
{
using var aes = Aes.Create();
aes.Key = _key;
aes.IV = _iv;
var decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
var cipherBytes = Convert.FromBase64String(cipherText);
var decryptedBytes = decryptor.TransformFinalBlock(cipherBytes, 0, cipherBytes.Length);
return Encoding.UTF8.GetString(decryptedBytes);
}
}
Key Best Practices:
Store keys securely (Azure Key Vault, AWS KMS, environment variables).
Never log plain text sensitive fields.
Use AES-256 with random IV for maximum security.
Storing Encrypted Data in SQL Server
Suppose we have a Users table:
CREATE TABLE Users
(
Id INT PRIMARY KEY IDENTITY,
Email NVARCHAR(256) NOT NULL,
EncryptedPassword NVARCHAR(MAX) NOT NULL
);
Inserting encrypted password from ASP.NET Core:
var encryptedPassword = cryptoService.Encrypt(user.Password);
await dbContext.Users.AddAsync(new User
{
Email = user.Email,
EncryptedPassword = encryptedPassword
});
await dbContext.SaveChangesAsync();
Retrieving and decrypting:
var user = await dbContext.Users.FirstOrDefaultAsync(u => u.Email == email);
if (user != null)
{
var password = cryptoService.Decrypt(user.EncryptedPassword);
}
4. SQL Server Encryption Features
SQL Server provides built-in encryption mechanisms:
Transparent Data Encryption (TDE)
Encrypts entire database at rest automatically.
Minimal changes to application.
Useful for compliance (PCI, HIPAA).
Column-Level Encryption
INSERT INTO Users (Email, EncryptedPassword)
VALUES ('[email protected]', ENCRYPTBYPASSPHRASE('MyPassphrase', 'MySecretPassword'));
Decryption:
SELECT Email, CONVERT(NVARCHAR, DECRYPTBYPASSPHRASE('MyPassphrase', EncryptedPassword))
FROM Users;
Always Encrypted
Client driver encrypts/decrypts data automatically.
Backend never sees plain text.
Ideal for highly sensitive fields like SSNs, credit cards.
5. Angular + Backend Integration Best Practices
End-to-End Encryption: Encrypt in Angular if required by regulations.
Secure Transport: Always use HTTPS for API calls.
Backend Validation: Validate decrypted data before processing.
Key Rotation: Regularly rotate encryption keys and manage old keys safely.
Audit Logs: Track access to sensitive data without logging plaintext.
6. Hashing vs Encryption
| Use Case | Method | Notes |
|---|
| Passwords | Hashing (bcrypt) | Never decrypt passwords. Store only hash. |
| Credit Card / PII | AES / Always Encrypted | Can be decrypted for authorized use. |
| Token / Session Data | AES / HMAC | Can verify integrity and decrypt securely. |
Always hash passwords instead of encrypting. Use PBKDF2, bcrypt, or Argon2 for secure storage.
7. Security Considerations
Never hard-code keys in Angular or backend code.
Limit sensitive data exposure in logs or error messages.
Use strong key derivation (PBKDF2, HKDF) if deriving encryption keys.
Access Control: Only authorized services should decrypt sensitive data.
Regular Penetration Testing: Validate implementation against common attacks.
8. Performance Considerations
AES encryption is fast, but avoid encrypting/decrypting large blobs frequently.
For database-heavy workloads, consider TDE + application-level encryption for critical fields only.
Cache decrypted results in memory if needed, but never persist in plain text.
Always profile encryption overhead in production.
9. Optional Enhancements
Secure Key Management: Azure Key Vault, AWS KMS, HashiCorp Vault.
Field-Level Access Control: Only specific roles can request decryption.
Client-Side Masking: Mask data in UI while still encrypted in storage.
Tokenization: Replace sensitive fields with secure tokens if full decryption is not required.
10. Summary
Encrypting sensitive data in Angular + ASP.NET Core + SQL Server requires a layered approach:
HTTPS for data in transit.
Application-layer encryption for sensitive fields (AES-256 recommended).
Database encryption using Always Encrypted or TDE.
Secure key management and rotation.
Hash passwords using strong algorithms, never encrypt for storage.
With this strategy, you ensure:
Regulatory compliance (GDPR, PCI DSS, HIPAA).
Protection against data breaches.
Secure and maintainable architecture for enterprise applications.