2020年9月12日星期六
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))