¿Sabemos cómo crear y almacenar contraseñas seguras?


Las contraseñas se usan mucho para reforzar el acceso a los recursos. Los atacantes usarán muchas técnicas para descubrir las contraseñas de los usuarios y conseguir acceso no autorizado a recursos o datos.
Para protegerse mejor, es importante que entienda en qué consiste una contraseña segura y cómo almacenarla en forma segura.

En este humilde post vamos a intentar comprender un poco como deberíamos usar contraseñas seguras.

Photo by M Venter on Pexels.com

Creación de una contraseña segura

Las contraseñas seguras tienen cuatro requisitos principales que se detallan a continuación por orden de importancia:

  • El usuario debe poder recordar la contraseña fácilmente
  • Otra persona no debe poder adivinar la contraseña.
  • Un programa no debe poder adivinar ni descubrir la contraseña.
  • Debe ser compleja, incluyendo números, símbolos y una combinación de letras mayúsculas y minúsculas. Basándose en la lista anterior, el primer requisito, probablemente, sea el más importante porque usted debe poder recordar su contraseña. Por ejemplo, la contraseña «#4sFrX^-aartPOknx25_70!xAdk»

Una excelente forma de crear contraseñas seguras es elegir cuatro o más palabras al azar y concatenarlas. La contraseña «televisionranabotasiglesia» es más segura que «J0n@que#81». Observe que, si bien la segunda contraseña cumple con las políticas antes descritas, los programas descifradores de contraseñas (cracks) son muy eficientes para detectar este tipo de contraseña. Aunque muchos conjuntos de directivas de contraseña no aceptarán la primera contraseña, «televisionranabotasiglesia», esta es mucho más segura que la segunda.

Es mucho más fácil de recordar para el usuario (especialmente, si está asociada con una imagen), es muy larga y su factor aleatorio hace que sea más difícil de adivinar para los programas descifradores de contraseñas.
Con una herramienta de creación de contraseñas en línea, cree contraseñas basadas en el conjunto común
de directivas de contraseña para empresas antes descrito.

  • Abra un navegador web y vaya a http://passwordsgenerator.net.
  • Seleccione las opciones para cumplir con el conjunto de directivas de contraseña.
  • Genere la contraseña.


¿La contraseña generada es fácil de recordar?

Mediante una herramienta de creación de contraseñas en línea, cree contraseñas basadas en palabras
al azar. Tenga en cuenta que, como las palabras se escriben unidas, no se consideran como palabras
del diccionario.

Almacenamiento seguro de contraseñas
Si el usuario elige usar un administrador de contraseñas, la primera característica de una contraseña segura puede ignorarse porque el usuario tiene acceso al administrador de contraseñas en todo momento. Tenga presente que algunos usuarios solo confían en su propia memoria para guardar sus contraseñas. Los administradores de contraseñas, tanto locales como remotos, deben tener un almacén de contraseñas, que podría verse comprometido.
El almacén de contraseñas del administrador de contraseñas debe tener un cifrado seguro y el acceso a este debe controlarse estrictamente. Gracias a aplicaciones de teléfonos móviles e interfaces web, los
administradores de contraseñas basados en la nube ofrecen acceso ininterrumpido y en cualquier momento a los usuarios

¿Qué es una contraseña segura?
Teniendo presentes las características de contraseña segura provistas al inicio de este post, elija una
contraseña que sea fácil de recordar pero difícil de adivinar. Está bien usar contraseñas complejas siempre que no afecten requisitos más importantes como la capacidad para recordarlas fácilmente.
Si se usa un administrador de contraseñas, la necesidad de que puedan recordarse fácilmente puede
omitirse.
A continuación, se proporciona un resumen rápido:

  • Elija una contraseña que pueda recordar.
  • Elija una contraseña que otra persona no pueda asociar con usted.
  • Elija contraseñas diferentes y nunca use la misma contraseña para servicios diferentes.
  • Está bien usar contraseñas complejas siempre que esto no las haga difíciles de recordar.

¿Que significa MLE?


Las siglas MLE corresponden al algoritmo de estimación de máxima verosimilitud y se usa por ejemplo para la desagregación de energía.

Es responsable cuando se desea un solo aparato desagregado en lugar de desagregar muchos. Además, el aparato debe ser mayoritariamente resistivo para lograr precisión.

Se basa en eventos emparejados:

- OnPower: valor delta cuando el aparato está encendido. 
- OffPOwer: valor delta cuando el aparato está apagado. 
- Duración: duración entre encendido y apagado.

Además, para descartar muchos eventos poco probables, se establecen tres restricciones:

- PowerNoise: valor delta mínimo por debajo del cual el delta se considera ruido. 
- PowerPair: diferencia máxima entre OnPower y OffPower (considerando electrodomésticos con consumo de energía constante).
 - timeWindow: marco de tiempo máximo entre Onpower y Offpower.

Las características antes mencionadas se modelan con gaussianas, mezclas gaussianas o Poisson. Para cada evento emparejado entrante, el algoritmo extraerá estas tres características y evaluará la probabilidad de máxima verosimilitud de que ese evento emparejado sea un dispositivo determinado.

IMPORTACIONES

import numpy as np
import pandas as pd
from os.path import join
from pylab import rcParams
import matplotlib.pyplot as plt
%matplotlib inline
rcParams['figure.figsize'] = (13, 6)
#plt.style.use('ggplot')
from datetime import datetime as datetime2
from datetime import timedelta

import nilmtk
from nilmtk.disaggregate.maximum_likelihood_estimation import MLE
from nilmtk import DataSet, TimeFrame, MeterGroup, HDFDataStore
from scipy.stats import poisson, norm
from sklearn import mixture
import warnings
warnings.filterwarnings("ignore")

Funciones

def get_all_appliances(appliance):

    # Filtering by appliances: 
    print "Fetching " + appliance + " over data loaded to nilmtk."
    metergroup = nilmtk.global_meter_group.select_using_appliances(type=appliance)
    
    if len(metergroup.appliances) == 0: 
        print "None " + appliance + " found on memory."
        pass

    # Selecting only single meters: 
    print "Filtering to get one meter for each " + appliance

    meters = [meter for meter in metergroup.meters if (len(meter.appliances) == 1)]
    metergroup = MeterGroup(meters)
    print metergroup
    print "Found " + str(len(metergroup.meters)) + " " + appliance

    return metergroup


def get_all_trainings(appliance, train):

    # Filtering by appliances: 
    print "Fetching " + appliance + " over data train data."
    elecs = []
    for building in train.buildings: 
        print "Building " + str(building) + "..."
        elec = train.buildings[building].elec[appliance]
        if len(elec.appliances) == 1: 
            print elec
            print "Fetched elec."
            elecs.append(elec)

        else: 
            print elec
            print "Groundtruth does not exist. Many appliances or None"

    metergroup = MeterGroup(elecs)

    return metergroup

Cargando datos

path = '../../../nilmtk/data/ukdale'
ukdale = train = DataSet(join(path, 'ukdale.h5'))

Y dividir en datos de prueba y de entrenaminento

In [8]:train = DataSet(join(path, 'ukdale.h5'))
test = DataSet(join(path, 'ukdale.h5'))
train.set_window(end="17-5-2013")
test.set_window(start="17-5-2013")
#zoom.set_window(start="17-5-2013")
print('loaded ' + str(len(ukdale.buildings)) + ' buildings')

loaded 5 buildings

Obteniendo los datos de entrenamiento

Es posible que el dispositivo seleccionado no esté entrenado desde ElecMeters donde se presentan otros dispositivos, ya que podemos extraer la verdad básica

# Appliance to disaggregate: 
applianceName = 'kettle'
# Groundtruth from the training data: 
metergroup = get_all_trainings(applianceName,train)

Fetching kettle over data train data.
Building 1...
ElecMeter(instance=10, building=1, dataset='UK-DALE', appliances=[Appliance(type='kettle', instance=1), Appliance(type='food processor', instance=1), Appliance(type='toasted sandwich maker', instance=1)])
Groundtruth does not exist. Many appliances or None
Building 2...
ElecMeter(instance=8, building=2, dataset='UK-DALE', appliances=[Appliance(type='kettle', instance=1)])
Fetched elec.
Building 3...
ElecMeter(instance=2, building=3, dataset='UK-DALE', appliances=[Appliance(type='kettle', instance=1)])
Fetched elec.
Building 4...
ElecMeter(instance=3, building=4, dataset='UK-DALE', appliances=[Appliance(type='kettle', instance=1), Appliance(type='radio', instance=1)])
Groundtruth does not exist. Many appliances or None
Building 5...
ElecMeter(instance=18, building=5, dataset='UK-DALE', appliances=[Appliance(type='kettle', instance=1)])
Fetched elec.

Algoritmo MLE

Capacitación

Primero, creamos el modelo

mle = MLE()

Luego, actualizamos el parámetro del modelo con algunos valores de adivinación.

Primero adivine las características: mezclas gaussianas de encendido y apagado y poisson de duración.

# setting parameters in the model: 
mle.update(appliance=applianceName, resistive=True, units=('power','active'), thDelta= 1500, thLikelihood= 1e-10, powerNoise= 50, powerPair= 100, timeWindow= 400, sample_period= '10S', sampling_method='first')

# Settings the features parameters by guessing:  
mle.onpower = {'name':'gmm', 'model': mixture.GMM(n_components=2)}
mle.offpower = {'name':'gmm', 'model': mixture.GMM(n_components=2)}
mle.duration = {'name':'poisson', 'model': poisson(0)}

Updating model
{'resistive': True, 'appliance': 'kettle', 'sampling_method': 'first', 'sample_period': '10S', 'thLikelihood': 1e-10, 'timeWindow': 400, 'units': ('power', 'active'), 'thDelta': 1500, 'powerNoise': 50, 'powerPair': 100}

Entrenando el modelo

Entrenamos el modelo con todas las ocurrencias de ese modelo de dispositivo que se encuentran en los datos de entrenamiento.

mle.train(metergroup)

('kettle', 1)
Training on chunk
Samples of onpower: 214
Samples of offpower: 214
Samples of duration: 214
Training onpower
Training offpower
Training duration
('kettle', 2)
Training on chunk
Samples of onpower: 92
Samples of offpower: 92
Samples of duration: 92
Training onpower
Training offpower
Training duration
('kettle', 3)
Chunk empty

Y luego visualizamos características con featureHist_colors () para ver la distribución y cuántas muestras tenemos para cada dispositivo (el mismo modelo de diferentes casas).

mle.featuresHist_colors()


A veces, tenemos más eventos de algunas casas que de otras, como vemos en la figura de arriba. Por lo tanto, necesitamos recortar información para mantener el mismo número de muestras para cada casa.

mle.no_overfitting()

Retraining onpower
Retraining offpower
Retraining duration

In [15]:mle.featuresHist_colors()


Hay otra herramienta de visualización para ver cómo se ajustan las distribuciones del modelo a los datos:

mle.featuresHist()


Onpower y Offpower parecen encajar bien con los datos, pero necesitamos cambiar el modelo por duración

mle.duration = {'name':'gmm', 'model': mixture.GMM(n_components=10)}

Y luego volvemos a entrenar el modelo y usamos no_overfitting

mle.train(metergroup)
mle.no_overfitting()
mle.featuresHist()

('kettle', 1)
Training on chunk
Samples of onpower: 214
Samples of offpower: 214
Samples of duration: 214
Training onpower
Training offpower
Training duration
('kettle', 2)
Training on chunk
Samples of onpower: 92
Samples of offpower: 92
Samples of duration: 92
Training onpower
Training offpower
Training duration
('kettle', 3)
Chunk empty
Retraining onpower
Retraining offpower
Retraining duration

Una vez que tengamos la distribución del modelo final para cada característica. Necesitamos la integridad de cada distribución. Cada CDF debe estar delimitado por uno.

mle.check_cdfIntegrity(step=10)

Onpower cdf: 0.986177684776
Offpower cdf: 1.0
Duration cdf: 0.987375070732

Desagregación

# Building to disaggregate: 
building = 2
mains = test.buildings[building].elec.mains()

# File to store the disaggregation
filename= '/home/energos/Escritorio/ukdale-disag-ml.h5'
output = HDFDataStore(filename, 'w')

El siguiente paso tomará unos minutos.

mle.disaggregate(mains, output)

25656 events found.
12419 onEvents found
4244 onEvents no paired.
1 chunks disaggregated

También recibimos cierta información, como el número total de eventos, el número de eventos de encendido, el número de eventos que no se han emparejado y los fragmentos desglosados.

Comparando la desagregación con la verdad básica

## Groundtruth
kettle = test.buildings[building].elec.select_using_appliances(type=applianceName)
output.load(mains.key).next().plot()
kettle.plot()
output.close()