2020年9月8日星期二

AES-GCM: The Authenticated Cipher Standard - TLS 1.2 used


AES-GCM’s biggest weakness is its fragility in the face of nonce repetition. If the same nonce N is used twice in an AES-GCM implementation, an attacker can get the authentication key H and use it to forge tags for any ciphertext, associated data, or combination thereof

OCB is a bit less fragile than GCM against repeated nonces. For example, if a nonce is used twice, an attacker that sees the two ciphertexts will notice that, say, the third plaintext block of the first message is identical to the third plaintext block of the second message. With GCM, attackers can find not only duplicates but also XOR differences between blocks at the same position. The impact of repeated nonces is therefore worse with GCM than it is with OCB.

Synthetic IV, not streamable, also known as SIV, is an authenticated cipher mode typically used with AES. Unlike GCM and OCB, SIV is secure even if you use the same nonce twice: if an attacker gets two ciphertexts encrypted using the same nonce, they’ll only be able to learn whether the same plaintext was encrypted twice. Unlike with messages encrypted with GCM or OCB, the attacker would be unable to tell whether the first block of the two messages is the same because the nonce used to encrypt is first computed as a combination of the given nonce and the plaintext

The document RFC 5297, based on the 2006 paper “Deterministic Authenticated-Encryption” by Rogaway and Shrimpton, specifies SIV as using CMAC-AES (a MAC construction using AES) as a PRF and AES- CTR as a cipher. In 2015, a more efficient version of SIV was proposed, called GCM-SIV, that combines GCM’s fast GHASH function and SIV’s mode and is nearly as fast as GCM. Like the original SIV, however, GCM-SIV isn’t streamable.


TLS 1.3 supports only three algorithms: AES-GCM, AES-CCM (a slightly less efficient mode than GCM), and the ChaCha20 stream cipher combined with the Poly1305 MAC (as defined in RFC 7539). Because TLS 1.3 prevents you from using an unsafe key length such as 64 or 80 bits (which are both too short), the secret key can be either 128 bits (AES-GCM or AES-CCM) or 256 bits (AES-GCM or ChaCha20-Poly1305).





MTU

 Router(config-if)# crypto ipsec fragmentation before-encryption

Router(config-if)# crypto ipsec fragmentation after-encryption


Router(config)# interface tunnel 4 

Router(config-if)# ip tcp adjust-mss 1360

Router(config-if)# ip mtu 1400


Router(config)# interface tunnel 6 

Router(config-if)# ipv6 tcp adjust-mss 1340

Router(config-if)# ipv6 mtu 1400


One method to test and detect a reduced MTU size is to use a ping with a large packet size. Here are some examples of how to do this.

C:\Users\ScottHogg> ping -l 1500 192.168.10.1

On a Windows host you can also set the Do Not Fragment (DF) bit to 1 with the “-f” ping parameter.

Content Continues Below

Ad

C:\Users\ScottHogg> ping 192.168.10.1 -l 1500 –f

On Linux the command would be:

RedHat# ping -s 1500 -M do 192.168.10.1

On a Cisco IOS device the command would be:

Content Continues Below

Router1# ping 192.168.10.1 size 1500 df-bit

On a Cisco NX-OS device the command would be: 

Switch7K# ping 192.168.10.1 packet-size 9216 c 10

On a Cisco IOS XR device the command would be:

 Content Continues Below

RP/0/RP0/CPU0:Router1#ping 192.168.10.1 size 1500 donnotfrag

On a JUNOS device the command would look like:

root@J4350-1# run ping 192.168.10.1 size 1500 do-not-fragment rapid

Elliptic curve example from book

 Elliptic curve


epoints := proc(ec, x, ub, p)

local ecurve, z, pct, k, i;

pct := 0;

for k from 0 to p-1 while pct <= ub do

        z := subs(x=k, ec) mod p;

        if z = 0 then

pct := pct + 1;

           ecurve[pct] := [k, z];

        fi:

if z &^ ((p-1)/2) mod p = 1 then

z := z &^ ((p+1)/4) mod p; ecurve[pct+1] := [k, z]; ecurve[pct+2] := [k, -z mod p]; pct := pct + 2;

fi: od:

    if pct > ub then

       pct := ub:

fi:

seq(ecurve[i], i = 1..pct): end:

addec := proc(le, re, c, p)

    local i, cle, cre, lambda, res, x3, y3;

    cle := le mod p;

    cre := re mod p;

    if cle = 0 or cre = 0 then

res := cle + cre;

elif cle[1] = cre[1] and cle[2] = -cre[2] mod p then

res := 0; else

       if cle[1] = cre[1] mod p and cle[2] = cre[2] mod p

       then

lambda := ((3*cle[1]^2+c)/2/cle[2]) mod p; else

lambda := (cre[2]-cle[2])/(cre[1]-cle[1]) mod p; fi:


x3 := (lambda^2-cle[1]-cre[1]) mod p;

y3 := (lambda*(cle[1]-x3)-cle[2]) mod p; res := [x3, y3];

fi:

res; end:

elgamal := proc(alpha, e, c, p)

    local calpha, n, y;

    read(addec);

    calpha := alpha;

    n := e;

    y := 0;

    while n > 0 do

        if irem(n, 2, ’n’) = 1 then

           y := addec(calpha, y, c, p):

fi:

        calpha := addec(calpha, calpha, c, p):

    od:

y; end:



a := epoints(eqn, x, 1, p);

b := elgamal(a, n, c, p);

k := 431235145514:

y := elgamal(a, k, c, p);

kb := elgamal(b, k, c, p);

w := [1704130304252114, 2018001913141413]:

z := [ kb[1]*w[1] mod p, kb[2]*w[2] mod p ];

ny := elgamal(y, n, c, p);



The field of post-quantum cryptography is about designing public-key algorithms that cannot be broken by a quantum computer; that is, they would be quantum safe and able to replace RSA and elliptic curve–based algorithms in a future

CBC and CTR script from book

 CBC


#!/usr/bin/env python

from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.backends import default_backend

from binascii import hexlify as hexa

from os import urandom

BLOCKLEN = 16

# the blocks() function splits a data string into space-separated blocks def blocks(data):

    split = [hexa(data[i:i+BLOCKLEN]) for i in range(0, len(data), BLOCKLEN)]

return ' '.join(split) k = urandom(16)

print 'k = %s' % hexa(k)

# pick a random IV

iv = urandom(16)

print 'iv = %s' % hexa(iv)

# pick an instance of AES in CBC mode

aes = Cipher(algorithms.AES(k), modes.CBC(iv), backend=default_backend()).encryptor()

p = '\x00'*BLOCKLEN*2

c = aes.update(p) + aes.finalize()

print 'enc(%s) = %s' % (blocks(p), blocks(c)) # now with a different IV and the same key

iv = urandom(16) 

print 'iv = %s' % hexa(iv)

aes = Cipher(algorithms.AES(k), modes.CBC(iv), backend=default_backend()).encryptor()

c = aes.update(p) + aes.finalize()

print 'enc(%s) = %s' % (blocks(p), blocks(c))


CTR mode


#!/usr/bin/env python

from Crypto.Cipher import AES

from Crypto.Util import Counter

from binascii import hexlify as hexa from os import urandom

from struct import unpack

k = urandom(16)

print 'k = %s' % hexa(k)

# pick a starting value for the counter nonce = unpack('<Q', urandom(8))[0]

# instantiate a counter function

ctr = Counter.new(128, initial_value=nonce)

# pick an instance of AES in CTR mode, using ctr as counter

aes = AES.new(k, AES.MODE_CTR, counter=ctr)

# no need for an entire block with CTR

p = '\x00\x01\x02\x03'

# encrypt p

c = aes.encrypt(p)

print 'enc(%s) = %s' % (hexa(p), hexa(c))

# decrypt using the encrypt function

ctr = Counter.new(128, initial_value=nonce) aes = AES.new(k, AES.MODE_CTR, counter=ctr) p = aes.encrypt(c)

print 'enc(%s) = %s' % (hexa(c), hexa(p))