Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New OpenPGP Specification #525

Open
wants to merge 45 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
25ae534
Initial implementation of Argon2 (ported from bc-java)
roughconsensusandrunningcode Feb 8, 2024
fa13755
New algorithms and packet types
roughconsensusandrunningcode Feb 10, 2024
5dcbac6
Padding Packet support
roughconsensusandrunningcode Feb 11, 2024
091b92e
Initial support for Version6 keys and signatures
roughconsensusandrunningcode Feb 13, 2024
182c2ae
basic creation of v6 public keys
roughconsensusandrunningcode Feb 14, 2024
31f2b98
check correct salt size in v6 signature packets
roughconsensusandrunningcode Feb 15, 2024
3edb702
refactored SecretKeyPacket (based on java version)
roughconsensusandrunningcode Feb 15, 2024
ad9b9b2
refactored S2k class (based on java version)
roughconsensusandrunningcode Feb 15, 2024
244eaa0
Packet criticality
roughconsensusandrunningcode Feb 22, 2024
683e76f
verify v6 key binding signatures
roughconsensusandrunningcode Feb 22, 2024
3105084
parse and verify v6 One-Pass Signatures
roughconsensusandrunningcode Feb 23, 2024
a613784
generate v6 signatures
roughconsensusandrunningcode Feb 28, 2024
ceaa293
test v6 inline signature generate and verify
roughconsensusandrunningcode Feb 29, 2024
4dfe4ad
Merge branch 'bcgit:master' into crypto-refresh
roughconsensusandrunningcode Feb 29, 2024
f4ac85c
doc comments
roughconsensusandrunningcode Feb 29, 2024
a8ce4b0
v5 keys and signature verification, tests on multiple v4+v6 signatures
roughconsensusandrunningcode Mar 2, 2024
6c933f2
generation of v6 OpenPGP keypairs
roughconsensusandrunningcode Mar 3, 2024
fd0da13
test adding encryption subkeys in v6 keyrings
roughconsensusandrunningcode Mar 3, 2024
cf27aea
small modifications in tests
roughconsensusandrunningcode Mar 4, 2024
a9c2208
"Version" and "Hash" Armor Header only on explicit request
roughconsensusandrunningcode Mar 5, 2024
b10b3f1
Merge branch 'bcgit:master' into crypto-refresh
roughconsensusandrunningcode Mar 7, 2024
f939a07
Review PgpSecretKey class
roughconsensusandrunningcode Mar 12, 2024
13b9d9f
Merge branch 'crypto-refresh' of https://github.com/roughconsensusand…
roughconsensusandrunningcode Mar 12, 2024
d7e7d09
Merge branch 'bcgit:master' into crypto-refresh
roughconsensusandrunningcode Mar 12, 2024
b0b65bc
Merge branch 'bcgit:master' into crypto-refresh
roughconsensusandrunningcode Mar 27, 2024
8554d8f
Merge branch 'bcgit:master' into crypto-refresh
roughconsensusandrunningcode Apr 9, 2024
e0ce83b
SKESK v6 decryption
roughconsensusandrunningcode Apr 13, 2024
32dbbd0
Merge branch 'argon2' into crypto-refresh
roughconsensusandrunningcode Apr 13, 2024
16e7329
Support for Argon2 s2k in SKESK and PgpSecretKey decryption
roughconsensusandrunningcode Apr 14, 2024
cb26579
V6 PKESK decryption
roughconsensusandrunningcode Apr 16, 2024
b063307
V4 SKESK + V1 SEIPD Encryption with Argon2 s2k
roughconsensusandrunningcode Apr 18, 2024
68d3821
V3 PKESK + V1 SEIPD Encryption with X25519 and X448
roughconsensusandrunningcode Apr 20, 2024
5e72362
AEAD Encryption - V6 PKESK, V6 SKESK, V2 SEIPD
roughconsensusandrunningcode Apr 24, 2024
b0848c0
Correct usage of RSA and ECDH in V6 PKESK
roughconsensusandrunningcode Apr 25, 2024
bdbb66c
Update references to "crypto-refresh" to point to RFC 9580.
roughconsensusandrunningcode Aug 16, 2024
a1496ef
Feature flag for Version 2 SEIPD
roughconsensusandrunningcode Sep 28, 2024
28db83e
Followup changes to Argon2 PR
peterdettman Oct 2, 2024
55361bd
Followup changes to Argon2 in OpenPGP
roughconsensusandrunningcode Oct 3, 2024
f9182de
Add XorBothTo methods to Nat(512)
peterdettman Oct 3, 2024
d396a19
Refactoring in Argon2
peterdettman Oct 3, 2024
6940300
Adapt PgpUtilities.DoMakeKeyFromPassPhrase to Argon2 Refactoring
roughconsensusandrunningcode Oct 5, 2024
1e57feb
Add various fingerprint-related methods in OpenPgp
peterdettman Apr 10, 2024
2805fb1
merge master branch
roughconsensusandrunningcode Dec 5, 2024
ea6a5b3
followup changes
roughconsensusandrunningcode Dec 5, 2024
8ad4e84
BitStrength for RFC 9580 pubkey algorithms
roughconsensusandrunningcode Dec 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions crypto/src/bcpg/AeadAlgorithmTag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,17 @@ public enum AeadAlgorithmTag : byte
Eax = 1, // EAX (IV len: 16 octets, Tag len: 16 octets)
Ocb = 2, // OCB (IV len: 15 octets, Tag len: 16 octets)
Gcm = 3, // GCM (IV len: 12 octets, Tag len: 16 octets)

Experimental_1 = 100,
Experimental_2 = 101,
Experimental_3 = 102,
Experimental_4 = 103,
Experimental_5 = 104,
Experimental_6 = 105,
Experimental_7 = 106,
Experimental_8 = 107,
Experimental_9 = 108,
Experimental_10 = 109,
Experimental_11 = 110,
}
}
29 changes: 25 additions & 4 deletions crypto/src/bcpg/AeadEncDataPacket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ public class AeadEncDataPacket
private readonly byte m_chunkSize;
private readonly byte[] m_iv;

public const int Version1 = 1;

public AeadEncDataPacket(BcpgInputStream bcpgIn)
: base(bcpgIn)
: base(bcpgIn, PacketTag.ReservedAeadEncryptedData)
{
m_version = bcpgIn.RequireByte();
if (m_version != 1)
if (m_version != Version1)
throw new ArgumentException("wrong AEAD packet version: " + m_version);

m_algorithm = (SymmetricKeyAlgorithmTag)bcpgIn.RequireByte();
Expand All @@ -36,9 +38,9 @@ public AeadEncDataPacket(BcpgInputStream bcpgIn)

public AeadEncDataPacket(SymmetricKeyAlgorithmTag algorithm, AeadAlgorithmTag aeadAlgorithm, int chunkSize,
byte[] iv)
: base(null)
: base(null, PacketTag.ReservedAeadEncryptedData)
{
m_version = 1;
m_version = Version1;
m_algorithm = algorithm;
m_aeadAlgorithm = aeadAlgorithm;
m_chunkSize = (byte)chunkSize;
Expand Down Expand Up @@ -69,5 +71,24 @@ public static int GetIVLength(AeadAlgorithmTag aeadAlgorithm)
throw new ArgumentException("unknown mode: " + aeadAlgorithm);
}
}

public byte[] GetAAData()
{
return CreateAAData(Version, Algorithm, AeadAlgorithm, ChunkSize);
}

public static byte[] CreateAAData(int version, SymmetricKeyAlgorithmTag symAlgorithm, AeadAlgorithmTag aeadAlgorithm, int chunkSize)
{
byte[] aaData = new byte[]
{
0xC0 | (byte)PacketTag.ReservedAeadEncryptedData,
(byte)version,
(byte)symAlgorithm,
(byte)aeadAlgorithm,
(byte)chunkSize
};

return aaData;
}
}
}
191 changes: 191 additions & 0 deletions crypto/src/bcpg/AeadInputStream.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Utilities;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.IO;
using System;
using System.IO;

namespace Org.BouncyCastle.Bcpg
{
internal class AeadInputStream
: BaseInputStream
{
// ported from bc-java

private readonly Stream inputStream;
private readonly byte[] buf;
private readonly BufferedAeadBlockCipher cipher;
private readonly KeyParameter secretKey;
private readonly byte[] aaData;
private readonly byte[] iv;
private readonly int chunkLength;
private readonly int tagLen;

private byte[] data;
private int dataOff;
private long chunkIndex = 0;
private long totalBytes = 0;
private readonly bool isV5StyleAead;

private static int GetChunkLength(int chunkSize)
{
return 1 << (chunkSize + 6);
}

/// <summary>
/// InputStream for decrypting AEAD encrypted data.
/// </summary>
/// <param name="inputStream">underlying InputStream</param>
/// <param name="cipher">encryption cipher</param>
/// <param name="secretKey">decryption key</param>
/// <param name="iv">initialization vector</param>
/// <param name="aeadAlgorithm">AEAD algorithm</param>
/// <param name="chunkSize">chunk size of the AEAD encryption</param>
/// <param name="aaData">associated data</param>
public AeadInputStream(
Stream inputStream,
BufferedAeadBlockCipher cipher,
KeyParameter secretKey,
byte[] iv,
AeadAlgorithmTag aeadAlgorithm,
int chunkSize,
byte[] aaData)
:this(false, inputStream, cipher, secretKey, iv, aeadAlgorithm, chunkSize, aaData)
{
}

/// <summary>
/// InputStream for decrypting AEAD encrypted data.
/// </summary>
/// <param name="isV5StyleAead">flavour of AEAD (OpenPGP v5 or v6)</param>
/// <param name="inputStream">underlying InputStream</param>
/// <param name="cipher">encryption cipher</param>
/// <param name="secretKey">decryption key</param>
/// <param name="iv">initialization vector</param>
/// <param name="aeadAlgorithm">AEAD algorithm</param>
/// <param name="chunkSize">chunk size of the AEAD encryption</param>
/// <param name="aaData">associated data</param>
public AeadInputStream(
bool isV5StyleAead,
Stream inputStream,
BufferedAeadBlockCipher cipher,
KeyParameter secretKey,
byte[] iv,
AeadAlgorithmTag aeadAlgorithm,
int chunkSize,
byte[] aaData)
{
this.inputStream = inputStream;
this.cipher = cipher;
this.secretKey = secretKey;
this.aaData = aaData;
this.iv = iv;
this.isV5StyleAead = isV5StyleAead;

chunkLength = GetChunkLength(chunkSize);
tagLen = AeadUtils.GetAuthTagLength(aeadAlgorithm);

buf = new byte[chunkLength + tagLen + tagLen]; // allow room for chunk tag and message tag

Streams.ReadFully(inputStream, buf, 0, tagLen + tagLen);

// load the first block
data = ReadBlock();
dataOff = 0;
}

public override int Read(byte[] buffer, int offset, int count)
{
Streams.ValidateBufferArguments(buffer, offset, count);

if (count == 0)
{
return 0;
}

if (data != null && dataOff == data.Length)
{
data = ReadBlock();
dataOff = 0;
}

if (data == null)
{
return 0;
}

int available = data.Length - dataOff;
int supplyLen = count < available ? count : available;
Array.Copy(data, dataOff, buffer, offset, supplyLen);
dataOff += supplyLen;

return supplyLen;
}

private byte[] ReadBlock()
{
int dataLen = Streams.ReadFully(inputStream, buf, tagLen + tagLen, chunkLength);
if (dataLen == 0)
{
return null;
}

byte[] adata = Arrays.Clone(aaData);
byte[] decData = new byte[dataLen];

try
{
AeadParameters aeadParams = new AeadParameters(
secretKey,
8 * tagLen,
AeadUtils.CreateNonce(iv, chunkIndex),
adata);

cipher.Init(false, aeadParams);

int len = cipher.ProcessBytes(buf, 0, dataLen + tagLen, decData, 0);

cipher.DoFinal(decData, len);
}
catch (InvalidCipherTextException e)
{
throw new IOException($"exception processing chunk {chunkIndex}: {e.Message}");
}

totalBytes += decData.Length;
chunkIndex++;
Array.Copy(buf, dataLen + tagLen, buf, 0, tagLen); // copy back the "tag"

if (dataLen != chunkLength)
{
// last block
try
{
adata = AeadUtils.CreateLastBlockAAData(isV5StyleAead, aaData, chunkIndex, totalBytes);
AeadParameters aeadParams = new AeadParameters(
secretKey,
8 * tagLen,
AeadUtils.CreateNonce(iv, chunkIndex),
adata);

cipher.Init(false, aeadParams);

cipher.ProcessBytes(buf, 0, tagLen, buf, 0);

cipher.DoFinal(buf, 0); // check final tag
}
catch (InvalidCipherTextException e)
{
throw new IOException($"exception processing final tag: {e.Message}");
}
}
else
{
Streams.ReadFully(inputStream, buf, tagLen, tagLen); // read the next tag bytes
}

return decData;
}
}
}
Loading