Skip to main content

Overview

SMAF implements encryption to protect sensitive data including connection strings, user credentials, and configuration parameters. The system uses the Rijndael algorithm (AES) for symmetric encryption with hardcoded encryption keys.

Encryption Implementation

Rijndael/AES Encryption

The system implements Rijndael (Advanced Encryption Standard) through the MngEncriptacion class:
using System.Security.Cryptography;
using System.IO;

namespace InapescaWeb.DAL
{
    public class MngEncriptacion
    {
        private static byte[] _key = Encoding.ASCII.GetBytes("InapescaWeb");
        private static byte[] _iv = Encoding.ASCII.GetBytes("InapescaWeb.Mysql");
    }
}
Rijndael is the algorithm selected as the Advanced Encryption Standard (AES). The implementation uses symmetric key encryption with the same key for both encryption and decryption operations.

Encryption Method

The encryptString method encrypts plain text strings:
public static string encryptString(string cadena)
{
    string cadenaEncriptada = "";
    
    try
    {
        // Convert input string to bytes
        byte[] inputBytes = Encoding.ASCII.GetBytes(cadena);
        byte[] encripted;
        
        // Create Rijndael cipher
        RijndaelManaged cripto = new RijndaelManaged();
        
        using (MemoryStream ms = new MemoryStream(inputBytes.Length))
        {
            // Create crypto stream with encryptor
            using (CryptoStream objCryptoStream = new CryptoStream(
                ms, 
                cripto.CreateEncryptor(_key, _iv), 
                CryptoStreamMode.Write))
            {
                // Write encrypted data to stream
                objCryptoStream.Write(inputBytes, 0, inputBytes.Length);
                objCryptoStream.FlushFinalBlock();
                objCryptoStream.Close();
            }
            
            // Get encrypted bytes
            encripted = ms.ToArray();
        }
        
        // Convert to Base64 string for storage/transmission
        cadenaEncriptada = Convert.ToBase64String(encripted);
        
        return cadenaEncriptada;
    }
    catch (Exception ex)
    {
        return cadenaEncriptada;
    }
}

Encryption Process Flow

1

Convert to bytes

The input string is converted to a byte array using ASCII encoding.
2

Create cipher

A RijndaelManaged object is instantiated to perform the encryption.
3

Initialize crypto stream

A CryptoStream is created with the encryptor transform using the static key and IV.
4

Write encrypted data

The plain text bytes are written to the crypto stream, which encrypts them.
5

Finalize and encode

The encrypted bytes are converted to Base64 string format for safe storage and transmission.

Decryption Implementation

Decryption Method

The decripString method decrypts encrypted strings:
public static string decripString(string cadena)
{
    string cadenaDesencriptada = "";
    
    try
    {
        // Convert Base64 string back to bytes
        byte[] inputBytes = Convert.FromBase64String(cadena);
        byte[] resultBytes = new byte[inputBytes.Length];
        string textoLimpio = String.Empty;
        
        // Create Rijndael cipher
        RijndaelManaged cripto = new RijndaelManaged();
        
        using (MemoryStream ms = new MemoryStream(inputBytes))
        {
            // Create crypto stream with decryptor
            using (CryptoStream objCryptoStream = new CryptoStream(
                ms, 
                cripto.CreateDecryptor(_key, _iv), 
                CryptoStreamMode.Read))
            {
                // Read decrypted data
                using (StreamReader sr = new StreamReader(objCryptoStream, true))
                {
                    textoLimpio = sr.ReadToEnd();
                }
            }
        }
        
        cadenaDesencriptada = textoLimpio;
        
        return cadenaDesencriptada;
    }
    catch (Exception ex)
    {
        return cadenaDesencriptada;
    }
}

Decryption Process Flow

1

Decode Base64

The Base64 encoded string is converted back to its encrypted byte array.
2

Create cipher

A RijndaelManaged object is instantiated with the same configuration.
3

Initialize crypto stream

A CryptoStream is created with the decryptor transform using the same key and IV.
4

Read decrypted data

A StreamReader reads the plain text from the crypto stream.
5

Return plain text

The decrypted string is returned to the caller.

Key Management

Static Encryption Keys

The system uses hardcoded encryption keys:
private static byte[] _key = Encoding.ASCII.GetBytes("InapescaWeb");
private static byte[] _iv = Encoding.ASCII.GetBytes("InapescaWeb.Mysql");
_key
byte[]
Encryption Key: "InapescaWeb" (11 characters)Used as the symmetric key for encryption/decryption operations.
_iv
byte[]
Initialization Vector (IV): "InapescaWeb.Mysql" (17 characters)Provides additional randomization for the cipher.
Security Risk: Using hardcoded encryption keys is a significant security vulnerability. The keys are embedded in the source code and can be extracted through reverse engineering.Recommendations:
  • Store keys in secure configuration management systems (e.g., Azure Key Vault, AWS KMS)
  • Use environment variables or secure configuration files with restricted access
  • Implement key rotation policies
  • Use longer, more complex keys (at least 256 bits for AES-256)

Connection String Encryption

Encrypted Connection Strings

Database connection strings are stored encrypted in the application configuration:
public static MySqlConnection getConexionMysql()
{
    // Retrieve encrypted connection string from config
    string CadenaConexionEncriptada = 
        ConfigurationManager.AppSettings["localhost"];
    
    // Decrypt connection string
    string CadenaConexion = MngEncriptacion.decripString(
        CadenaConexionEncriptada
    );
    
    // Create connection with decrypted string
    ConexionMysql = new MySqlConnection(CadenaConexion);
    return ConexionMysql;
}

Multiple Database Connections

The system manages multiple encrypted connection strings:
// Main SMAF database
public static MySqlConnection getConexionMysql()
{
    string CadenaConexionEncriptada = 
        ConfigurationManager.AppSettings["localhost"];
    string CadenaConexion = 
        MngEncriptacion.decripString(CadenaConexionEncriptada);
    ConexionMysql = new MySqlConnection(CadenaConexion);
    return ConexionMysql;
}

// DGAIPP module database
public static MySqlConnection getConexionMysql_dgaipp()
{
    string CadenaConexionEncriptada = 
        ConfigurationManager.AppSettings["localhost_dgaipp"];
    string CadenaConexion = 
        MngEncriptacion.decripString(CadenaConexionEncriptada);
    ConexionMysql1 = new MySqlConnection(CadenaConexion);
    return ConexionMysql1;
}

// Contracts module database
public static MySqlConnection getConexionMysql_Contratos()
{
    string CadenaConexionEncriptada = 
        ConfigurationManager.AppSettings["localhostContratos"];
    string CadenaConexion = 
        MngEncriptacion.decripString(CadenaConexionEncriptada);
    ConexionMysql2 = new MySqlConnection(CadenaConexion);
    return ConexionMysql2;
}

// Query module database
public static MySqlConnection getConexionMysql_ModuloConsulta()
{
    string CadenaConexionEncriptada = 
        ConfigurationManager.AppSettings["RemoteModuloConsulta"];
    string CadenaConexion = 
        MngEncriptacion.decripString(CadenaConexionEncriptada);
    ConexionMysql = new MySqlConnection(CadenaConexion);
    return ConexionMysql;
}
All database connection strings are stored encrypted in the application configuration file and decrypted at runtime before creating database connections.

Password Encryption

User Authentication

During login, usernames are encrypted for transmission:
public static Usuario Acceso_Smaf(string psUbicacion, 
                                  string psUsuario, 
                                  string psPassword)
{
    string lsQuery = "SELECT DISTINCT USSER AS USUARIO, " +
                     "PASSWORD AS PASSWORD, NIVEL, PLAZA, PUESTO, " +
                     "SECRETARIA, ORGANISMO, DEPENDENCIA AS UBICACION, " +
                     "AREA, NOMBRE, APELLIDO_PAT, APELLIDO_MAT, " +
                     "RFC, CARGO, EMAIL, ROL, ABREVIATURA " +
                     "FROM vw_usuarios " +
                     "WHERE USSER = '" + MngEncriptacion.decripString(psUsuario) + "' " +
                     "AND PASSWORD = '" + psPassword + "'";
}
Password Security Issue: Passwords are stored and compared in plain text. This is a critical security vulnerability.Current Implementation:
  • Usernames are encrypted during transmission
  • Passwords are stored as plain text in database
  • Passwords are compared directly without hashing
Recommended Solution:
  • Implement password hashing using bcrypt, PBKDF2, or Argon2
  • Store only the hash, never the plain text password
  • Add salt to prevent rainbow table attacks
  • Use timing-safe comparison to prevent timing attacks

Data Protection Strategies

Encryption at Rest

Currently encrypted data:
1

Connection strings

Database connection strings in configuration files are encrypted using Rijndael.
2

User credentials in transit

Usernames are encrypted when transmitted from client to server during authentication.

Data Not Encrypted

The following sensitive data is NOT currently encrypted:
  • User passwords (stored in plain text)
  • Personal information (RFC, CURP, addresses)
  • Financial data (expense amounts, budget figures)
  • Email addresses and contact information

Encryption Best Practices

Current Implementation Issues

1

Hardcoded keys

Issue: Encryption keys are hardcoded in source code.Risk: Keys can be extracted through reverse engineering.Solution: Move keys to secure key management system.
2

Weak key strength

Issue: Key is only 11 bytes (88 bits), IV is 17 bytes.Risk: Insufficient key length for strong encryption.Solution: Use minimum 256-bit (32-byte) keys for AES-256.
3

No key rotation

Issue: Keys are static and never changed.Risk: Long-term use increases vulnerability.Solution: Implement periodic key rotation policy.
4

Plain text passwords

Issue: Passwords stored without hashing.Risk: Database breach exposes all passwords.Solution: Implement password hashing with salt.
5

Limited error handling

Issue: Encryption errors return empty strings.Risk: Silent failures may lead to security issues.Solution: Log errors and implement proper error handling.
// Use configuration-based key management
public class MngEncriptacion
{
    private static byte[] GetEncryptionKey()
    {
        // Retrieve from secure key vault
        string keyFromVault = KeyVaultClient.GetSecret("EncryptionKey");
        return Convert.FromBase64String(keyFromVault);
    }
    
    private static byte[] GetIV()
    {
        string ivFromVault = KeyVaultClient.GetSecret("EncryptionIV");
        return Convert.FromBase64String(ivFromVault);
    }
}

Encryption Usage Examples

Encrypting Configuration Data

// Encrypt a connection string before storing in config
string plainConnectionString = 
    "Server=localhost;Database=smaf;Uid=user;Pwd=password;";
string encryptedConnectionString = 
    MngEncriptacion.encryptString(plainConnectionString);

// Store in configuration file
ConfigurationManager.AppSettings["localhost"] = encryptedConnectionString;

Decrypting Configuration Data

// Retrieve and decrypt connection string
string encryptedConnectionString = 
    ConfigurationManager.AppSettings["localhost"];
string plainConnectionString = 
    MngEncriptacion.decripString(encryptedConnectionString);

// Use decrypted connection string
MySqlConnection conn = new MySqlConnection(plainConnectionString);

Authentication with Encryption

// Client-side: Encrypt username before sending
string encryptedUsername = MngEncriptacion.encryptString(txtUsername.Text);
string password = txtPassword.Text;

// Send to server
Usuario user = MngDatosLogin.Acceso_Smaf(
    psUbicacion: selectedDepartment,
    psUsuario: encryptedUsername,
    psPassword: password
);

// Server-side: Decrypt username for query
string decryptedUsername = MngEncriptacion.decripString(psUsuario);

Security Audit Recommendations

1

Immediate actions

  • Implement password hashing for all user passwords
  • Move encryption keys to environment variables or key vault
  • Use AES-256 with proper key lengths
  • Enable HTTPS/TLS for all communications
2

Short-term improvements

  • Encrypt sensitive personal data (RFC, CURP, addresses)
  • Implement key rotation policy
  • Add comprehensive error logging for encryption operations
  • Implement database field-level encryption for sensitive columns
3

Long-term enhancements

  • Implement public key infrastructure (PKI) for certificate management
  • Add hardware security module (HSM) support
  • Implement data classification and encryption policies
  • Regular security audits and penetration testing

Compliance Considerations

For compliance with data protection regulations (e.g., Mexican Federal Data Protection Law):
  • Encrypt personal data at rest: RFC, CURP, addresses, contact information
  • Encrypt financial data: Salary information, expense amounts, bank details
  • Implement access logging: Track who accesses encrypted data
  • Key escrow: Maintain secure key backup for data recovery
  • Data retention: Encrypt archived data and implement secure deletion

Algorithm Specifications

Rijndael Configuration

Algorithm
string
Rijndael / AES (Advanced Encryption Standard)Symmetric block cipher used for encryption operations.
Key Size
integer
88 bits (11 bytes) - Current implementationRecommendation: Use 256 bits (32 bytes) for AES-256
IV Size
integer
136 bits (17 bytes) - Current implementationRecommendation: Use 128 bits (16 bytes) standard AES block size
Mode
string
CBC (Cipher Block Chaining) - Default modeRecommended for most use cases with proper IV management.
Padding
string
PKCS7 - Default padding schemeStandard padding for block ciphers.
Encoding
string
Base64 - Output encodingEncrypted bytes are encoded as Base64 strings for storage and transmission.

Build docs developers (and LLMs) love