diff --git a/crypto/src/asn1/Asn1InputStream.cs b/crypto/src/asn1/Asn1InputStream.cs
index 18d13c32d..501e788a0 100644
--- a/crypto/src/asn1/Asn1InputStream.cs
+++ b/crypto/src/asn1/Asn1InputStream.cs
@@ -2,7 +2,6 @@ using System;
using System.Diagnostics;
using System.IO;
-using Org.BouncyCastle.Asn1.Utilities;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Asn1
diff --git a/crypto/src/asn1/DerOutputStream.cs b/crypto/src/asn1/DerOutputStream.cs
index f95d123f9..c03d9dc11 100644
--- a/crypto/src/asn1/DerOutputStream.cs
+++ b/crypto/src/asn1/DerOutputStream.cs
@@ -1,7 +1,7 @@
using System;
using System.IO;
-using Org.BouncyCastle.Asn1.Utilities;
+using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Asn1
{
diff --git a/crypto/src/asn1/anssi/ANSSINamedCurves.cs b/crypto/src/asn1/anssi/ANSSINamedCurves.cs
index 04e30bb07..c7f9545f2 100644
--- a/crypto/src/asn1/anssi/ANSSINamedCurves.cs
+++ b/crypto/src/asn1/anssi/ANSSINamedCurves.cs
@@ -42,7 +42,7 @@ namespace Org.BouncyCastle.Asn1.Anssi
BigInteger h = BigInteger.One;
ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "B6B3D4C356C139EB31183D4749D423958C27D2DCAF98B70164C97A2DD98F5CFF"
+ "6142E0F7C8B204911F9271F0F3ECEF8C2701C307E8E4C9E183115A1554062CFB"));
diff --git a/crypto/src/asn1/misc/MiscObjectIdentifiers.cs b/crypto/src/asn1/misc/MiscObjectIdentifiers.cs
index 45adce4f7..8128b6952 100644
--- a/crypto/src/asn1/misc/MiscObjectIdentifiers.cs
+++ b/crypto/src/asn1/misc/MiscObjectIdentifiers.cs
@@ -41,13 +41,39 @@ namespace Org.BouncyCastle.Asn1.Misc
// iso/itu(2) country(16) us(840) organization(1) novell(113719)
//
public static readonly string Novell = "2.16.840.1.113719";
- public static readonly DerObjectIdentifier NovellSecurityAttribs = new DerObjectIdentifier(Novell + ".1.9.4.1");
+ public static readonly DerObjectIdentifier NovellSecurityAttribs = new DerObjectIdentifier(Novell + ".1.9.4.1");
//
// Entrust
// iso(1) member-body(16) us(840) nortelnetworks(113533) entrust(7)
//
public static readonly string Entrust = "1.2.840.113533.7";
- public static readonly DerObjectIdentifier EntrustVersionExtension = new DerObjectIdentifier(Entrust + ".65.0");
+ public static readonly DerObjectIdentifier EntrustVersionExtension = new DerObjectIdentifier(Entrust + ".65.0");
+
+ //
+ // Ascom
+ //
+ public static readonly DerObjectIdentifier as_sys_sec_alg_ideaCBC = new DerObjectIdentifier("1.3.6.1.4.1.188.7.1.1.2");
+
+ //
+ // Peter Gutmann's Cryptlib
+ //
+ public static readonly DerObjectIdentifier cryptlib = new DerObjectIdentifier("1.3.6.1.4.1.3029");
+
+ public static readonly DerObjectIdentifier cryptlib_algorithm = cryptlib.Branch("1");
+ public static readonly DerObjectIdentifier cryptlib_algorithm_blowfish_ECB = cryptlib_algorithm.Branch("1.1");
+ public static readonly DerObjectIdentifier cryptlib_algorithm_blowfish_CBC = cryptlib_algorithm.Branch("1.2");
+ public static readonly DerObjectIdentifier cryptlib_algorithm_blowfish_CFB = cryptlib_algorithm.Branch("1.3");
+ public static readonly DerObjectIdentifier cryptlib_algorithm_blowfish_OFB = cryptlib_algorithm.Branch("1.4");
+
+ //
+ // Blake2b
+ //
+ public static readonly DerObjectIdentifier blake2 = new DerObjectIdentifier("1.3.6.1.4.1.1722.12.2");
+
+ public static readonly DerObjectIdentifier id_blake2b160 = blake2.Branch("1.5");
+ public static readonly DerObjectIdentifier id_blake2b256 = blake2.Branch("1.8");
+ public static readonly DerObjectIdentifier id_blake2b384 = blake2.Branch("1.12");
+ public static readonly DerObjectIdentifier id_blake2b512 = blake2.Branch("1.16");
}
}
diff --git a/crypto/src/asn1/sec/SECNamedCurves.cs b/crypto/src/asn1/sec/SECNamedCurves.cs
index 0bd60b0b8..ca71a4e66 100644
--- a/crypto/src/asn1/sec/SECNamedCurves.cs
+++ b/crypto/src/asn1/sec/SECNamedCurves.cs
@@ -54,9 +54,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.One;
ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
- //ECPoint G = curve.DecodePoint(Hex.Decode("02"
- //+ "09487239995A5EE76B55F9C2F098"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "09487239995A5EE76B55F9C2F098"
+ "A89CE5AF8724C0A23E0E0FF77500"));
@@ -85,9 +83,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.ValueOf(4);
ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
- //ECPoint G = curve.DecodePoint(Hex.Decode("03"
- //+ "4BA30AB5E892B4E1649DD0928643"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "4BA30AB5E892B4E1649DD0928643"
+ "ADCD46F5882E3747DEF36E956E97"));
@@ -116,9 +112,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.One;
ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
- //ECPoint G = curve.DecodePoint(Hex.Decode("03"
- //+ "161FF7528B899B2D0C28607CA52C5B86"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "161FF7528B899B2D0C28607CA52C5B86"
+ "CF5AC8395BAFEB13C02DA292DDED7A83"));
@@ -147,9 +141,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.ValueOf(4);
ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
- //ECPoint G = curve.DecodePoint(Hex.Decode("02"
- //+ "7B6AA5D85E572983E6FB32A7CDEBC140"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "7B6AA5D85E572983E6FB32A7CDEBC140"
+ "27B6916A894D3AEE7106FE805FC34B44"));
@@ -191,9 +183,7 @@ namespace Org.BouncyCastle.Asn1.Sec
176);
ECCurve curve = ConfigureCurveGlv(new FpCurve(p, a, b, n, h), glv);
- //ECPoint G = curve.DecodePoint(Hex.Decode("02"
- //+ "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB"
+ "938CF935318FDCED6BC28286531733C3F03C4FEE"));
@@ -222,9 +212,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.One;
ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
- //ECPoint G = curve.DecodePoint(Hex.Decode("02"
- //+ "4A96B5688EF573284664698968C38BB913CBFC82"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "4A96B5688EF573284664698968C38BB913CBFC82"
+ "23A628553168947D59DCC912042351377AC5FB32"));
@@ -253,9 +241,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.One;
ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
- //ECPoint G = curve.DecodePoint(Hex.Decode("02"
- //+ "52DCB034293A117E1F4FF11B30F7199D3144CE6D"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "52DCB034293A117E1F4FF11B30F7199D3144CE6D"
+ "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E"));
@@ -297,9 +283,7 @@ namespace Org.BouncyCastle.Asn1.Sec
208);
ECCurve curve = ConfigureCurveGlv(new FpCurve(p, a, b, n, h), glv);
- //ECPoint G = curve.DecodePoint(Hex.Decode("03"
- //+ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"
+ "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D"));
@@ -328,9 +312,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.One;
ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
- //ECPoint G = curve.DecodePoint(Hex.Decode("03"
- //+ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"
+ "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811"));
@@ -372,9 +354,7 @@ namespace Org.BouncyCastle.Asn1.Sec
240);
ECCurve curve = ConfigureCurveGlv(new FpCurve(p, a, b, n, h), glv);
- //ECPoint G = curve.DecodePoint(Hex.Decode("03"
- //+ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C"
+ "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5"));
@@ -403,9 +383,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.One;
ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
- //ECPoint G = curve.DecodePoint(Hex.Decode("02"
- //+ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"
+ "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"));
@@ -447,9 +425,7 @@ namespace Org.BouncyCastle.Asn1.Sec
272);
ECCurve curve = ConfigureCurveGlv(new FpCurve(p, a, b, n, h), glv);
- //ECPoint G = curve.DecodePoint(Hex.Decode("02"
- //+ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
+ "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"));
@@ -478,9 +454,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.One;
ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
- //ECPoint G = curve.DecodePoint(Hex.Decode("03"
- //+ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"
+ "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"));
@@ -509,9 +483,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.One;
ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
- //ECPoint G = curve.DecodePoint(Hex.Decode("03"
- //+ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7"
+ "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F"));
@@ -540,9 +512,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.One;
ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
- //ECPoint G = curve.DecodePoint(Hex.Decode("02"
- //+ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"
+ "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"));
@@ -572,9 +542,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.ValueOf(2);
ECCurve curve = new F2mCurve(m, k, a, b, n, h);
- //ECPoint G = curve.DecodePoint(Hex.Decode("03"
- //+ "009D73616F35F4AB1407D73562C10F"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "009D73616F35F4AB1407D73562C10F"
+ "00A52830277958EE84D1315ED31886"));
@@ -604,9 +572,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.ValueOf(2);
ECCurve curve = new F2mCurve(m, k, a, b, n, h);
- //ECPoint G = curve.DecodePoint(Hex.Decode("03"
- //+ "01A57A6A7B26CA5EF52FCDB8164797"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "01A57A6A7B26CA5EF52FCDB8164797"
+ "00B3ADC94ED1FE674C06E695BABA1D"));
@@ -638,9 +604,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.ValueOf(2);
ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
- //ECPoint G = curve.DecodePoint(Hex.Decode("03"
- //+ "0081BAF91FDF9833C40F9C181343638399"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "0081BAF91FDF9833C40F9C181343638399"
+ "078C6E7EA38C001F73C8134B1B4EF9E150"));
@@ -672,9 +636,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.ValueOf(2);
ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
- //ECPoint G = curve.DecodePoint(Hex.Decode("03"
- //+ "0356DCD8F2F95031AD652D23951BB366A8"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "0356DCD8F2F95031AD652D23951BB366A8"
+ "0648F06D867940A5366D9E265DE9EB240F"));
@@ -706,9 +668,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.ValueOf(2);
ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
- //ECPoint G = curve.DecodePoint(Hex.Decode("03"
- //+ "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8"
+ "0289070FB05D38FF58321F2E800536D538CCDAA3D9"));
@@ -740,9 +700,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.ValueOf(2);
ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
- //ECPoint G = curve.DecodePoint(Hex.Decode("03"
- //+ "0369979697AB43897789566789567F787A7876A654"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "0369979697AB43897789566789567F787A7876A654"
+ "00435EDB42EFAFB2989D51FEFCE3C80988F41FF883"));
@@ -774,9 +732,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.ValueOf(2);
ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
- //ECPoint G = curve.DecodePoint(Hex.Decode("03"
- //+ "03F0EBA16286A2D57EA0991168D4994637E8343E36"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "03F0EBA16286A2D57EA0991168D4994637E8343E36"
+ "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1"));
@@ -806,9 +762,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.ValueOf(2);
ECCurve curve = new F2mCurve(m, k, a, b, n, h);
- //ECPoint G = curve.DecodePoint(Hex.Decode("03"
- //+ "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1"
+ "0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05"));
@@ -838,9 +792,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.ValueOf(2);
ECCurve curve = new F2mCurve(m, k, a, b, n, h);
- //ECPoint G = curve.DecodePoint(Hex.Decode("03"
- //+ "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F"
+ "01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C"));
@@ -870,9 +822,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.ValueOf(4);
ECCurve curve = new F2mCurve(m, k, a, b, n, h);
- //ECPoint G = curve.DecodePoint(Hex.Decode("02"
- //+ "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126"
+ "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3"));
@@ -902,9 +852,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.ValueOf(2);
ECCurve curve = new F2mCurve(m, k, a, b, n, h);
- //ECPoint G = curve.DecodePoint(Hex.Decode("03"
- //+ "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B"
+ "01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052"));
@@ -934,9 +882,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.ValueOf(4);
ECCurve curve = new F2mCurve(m, k, a, b, n, h);
- //ECPoint G = curve.DecodePoint(Hex.Decode("03"
- //+ "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC"
+ "76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA"));
@@ -968,9 +914,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.ValueOf(4);
ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
- //ECPoint G = curve.DecodePoint(Hex.Decode("02"
- //+ "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836"
+ "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259"));
@@ -1002,9 +946,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.ValueOf(2);
ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
- //ECPoint G = curve.DecodePoint(Hex.Decode("03"
- //+ "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053"
+ "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4"));
@@ -1034,9 +976,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.ValueOf(4);
ECCurve curve = new F2mCurve(m, k, a, b, n, h);
- //ECPoint G = curve.DecodePoint(Hex.Decode("03"
- //+ "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746"
+ "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B"));
@@ -1066,9 +1006,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.ValueOf(2);
ECCurve curve = new F2mCurve(m, k, a, b, n, h);
- //ECPoint G = curve.DecodePoint(Hex.Decode("03"
- //+ "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7"
+ "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706"));
@@ -1100,9 +1038,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.ValueOf(4);
ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
- //ECPoint G = curve.DecodePoint(Hex.Decode("02"
- //+ "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972"
+ "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3"));
@@ -1134,9 +1070,7 @@ namespace Org.BouncyCastle.Asn1.Sec
BigInteger h = BigInteger.ValueOf(2);
ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
- //ECPoint G = curve.DecodePoint(Hex.Decode("03"
- //+ "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19"));
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19"
+ "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B"));
diff --git a/crypto/src/asn1/teletrust/TeleTrusTNamedCurves.cs b/crypto/src/asn1/teletrust/TeleTrusTNamedCurves.cs
index f476619a7..ba3eda620 100644
--- a/crypto/src/asn1/teletrust/TeleTrusTNamedCurves.cs
+++ b/crypto/src/asn1/teletrust/TeleTrusTNamedCurves.cs
@@ -40,7 +40,7 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
return new X9ECParameters(
curve,
- curve.DecodePoint(Hex.Decode("04BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC31667CB477A1A8EC338F94741669C976316DA6321")), // G
+ new X9ECPoint(curve, Hex.Decode("04BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC31667CB477A1A8EC338F94741669C976316DA6321")), // G
n, h);
}
}
@@ -66,7 +66,7 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
return new X9ECParameters(
curve,
- curve.DecodePoint(Hex.Decode("04B199B13B9B34EFC1397E64BAEB05ACC265FF2378ADD6718B7C7C1961F0991B842443772152C9E0AD")), // G
+ new X9ECPoint(curve, Hex.Decode("04B199B13B9B34EFC1397E64BAEB05ACC265FF2378ADD6718B7C7C1961F0991B842443772152C9E0AD")), // G
n, h);
}
}
@@ -91,7 +91,7 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
return new X9ECParameters(
curve,
- curve.DecodePoint(Hex.Decode("04C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD614B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F")), // G
+ new X9ECPoint(curve, Hex.Decode("04C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD614B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F")), // G
n, h);
}
}
@@ -117,7 +117,7 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
return new X9ECParameters(
curve,
- curve.DecodePoint(Hex.Decode("043AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129097E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9")), // G'
+ new X9ECPoint(curve, Hex.Decode("043AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129097E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9")), // G'
n, h);
}
}
@@ -142,7 +142,7 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
return new X9ECParameters(
curve,
- curve.DecodePoint(Hex.Decode("040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD")), // G
+ new X9ECPoint(curve, Hex.Decode("040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD")), // G
n, h);
}
}
@@ -168,7 +168,7 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
return new X9ECParameters(
curve,
- curve.DecodePoint(Hex.Decode("046AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D5800374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C")), // G'
+ new X9ECPoint(curve, Hex.Decode("046AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D5800374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C")), // G'
n, h);
}
}
@@ -193,7 +193,7 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
return new X9ECParameters(
curve,
- curve.DecodePoint(Hex.Decode("048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997")), // G
+ new X9ECPoint(curve, Hex.Decode("048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997")), // G
n, h);
}
}
@@ -219,7 +219,7 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
return new X9ECParameters(
curve,
- curve.DecodePoint(Hex.Decode("04A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F42D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE")), // G'
+ new X9ECPoint(curve, Hex.Decode("04A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F42D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE")), // G'
n, h);
}
}
@@ -244,7 +244,7 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
return new X9ECParameters(
curve,
- curve.DecodePoint(Hex.Decode("0443BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E2061114FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1")), // G
+ new X9ECPoint(curve, Hex.Decode("0443BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E2061114FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1")), // G
n, h);
}
}
@@ -270,7 +270,7 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
return new X9ECParameters(
curve,
- curve.DecodePoint(Hex.Decode("04925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF3357F624A21BED5263BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B1B9BC0455FB0D2C3")), // G'
+ new X9ECPoint(curve, Hex.Decode("04925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF3357F624A21BED5263BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B1B9BC0455FB0D2C3")), // G'
n, h);
}
}
@@ -295,7 +295,7 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
return new X9ECParameters(
curve,
- curve.DecodePoint(Hex.Decode("041D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315")), // G
+ new X9ECPoint(curve, Hex.Decode("041D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315")), // G
n, h);
}
}
@@ -321,7 +321,7 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
return new X9ECParameters(
curve,
- curve.DecodePoint(Hex.Decode("0418DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928")), // G'
+ new X9ECPoint(curve, Hex.Decode("0418DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928")), // G'
n, h);
}
}
@@ -346,7 +346,7 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
return new X9ECParameters(
curve,
- curve.DecodePoint(Hex.Decode("0481AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F8227DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892")), // G
+ new X9ECPoint(curve, Hex.Decode("0481AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F8227DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892")), // G
n, h);
}
}
@@ -372,7 +372,7 @@ namespace Org.BouncyCastle.Asn1.TeleTrust
return new X9ECParameters(
curve,
- curve.DecodePoint(Hex.Decode("04640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332")), // G'
+ new X9ECPoint(curve, Hex.Decode("04640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332")), // G'
n, h);
}
}
diff --git a/crypto/src/asn1/util/FilterStream.cs b/crypto/src/asn1/util/FilterStream.cs
index 2b0494b78..980e7f176 100644
--- a/crypto/src/asn1/util/FilterStream.cs
+++ b/crypto/src/asn1/util/FilterStream.cs
@@ -3,8 +3,10 @@ using System.IO;
namespace Org.BouncyCastle.Asn1.Utilities
{
+ [Obsolete("Use Org.BouncyCastle.Utilities.IO.FilterStream")]
public class FilterStream : Stream
{
+ [Obsolete("Use Org.BouncyCastle.Utilities.IO.FilterStream")]
public FilterStream(Stream s)
{
this.s = s;
diff --git a/crypto/src/asn1/x509/AlgorithmIdentifier.cs b/crypto/src/asn1/x509/AlgorithmIdentifier.cs
index 4ed3a400d..c6f4af5bf 100644
--- a/crypto/src/asn1/x509/AlgorithmIdentifier.cs
+++ b/crypto/src/asn1/x509/AlgorithmIdentifier.cs
@@ -69,11 +69,22 @@ namespace Org.BouncyCastle.Asn1.X509
}
}
+ /// <summary>
+ /// Return the OID in the Algorithm entry of this identifier.
+ /// </summary>
+ public virtual DerObjectIdentifier Algorithm
+ {
+ get { return objectID; }
+ }
+
public virtual DerObjectIdentifier ObjectID
{
get { return objectID; }
}
+ /// <summary>
+ /// Return the parameters structure in the Parameters entry of this identifier.
+ /// </summary>
public Asn1Encodable Parameters
{
get { return parameters; }
diff --git a/crypto/src/asn1/x9/ECNamedCurveTable.cs b/crypto/src/asn1/x9/ECNamedCurveTable.cs
index d8315c16f..92d4393a8 100644
--- a/crypto/src/asn1/x9/ECNamedCurveTable.cs
+++ b/crypto/src/asn1/x9/ECNamedCurveTable.cs
@@ -49,6 +49,28 @@ namespace Org.BouncyCastle.Asn1.X9
return ecP;
}
+ public static string GetName(DerObjectIdentifier oid)
+ {
+ string name = X962NamedCurves.GetName(oid);
+ if (name == null)
+ {
+ name = SecNamedCurves.GetName(oid);
+ }
+ if (name == null)
+ {
+ name = NistNamedCurves.GetName(oid);
+ }
+ if (name == null)
+ {
+ name = TeleTrusTNamedCurves.GetName(oid);
+ }
+ if (name == null)
+ {
+ name = AnssiNamedCurves.GetName(oid);
+ }
+ return name;
+ }
+
/**
* return the object identifier signified by the passed in name. Null
* if there is no object identifier associated with name.
diff --git a/crypto/src/asn1/x9/X962NamedCurves.cs b/crypto/src/asn1/x9/X962NamedCurves.cs
index a9ea0240c..6fa4e7c4b 100644
--- a/crypto/src/asn1/x9/X962NamedCurves.cs
+++ b/crypto/src/asn1/x9/X962NamedCurves.cs
@@ -38,7 +38,7 @@ namespace Org.BouncyCastle.Asn1.X9
return new X9ECParameters(
cFp192v1,
- cFp192v1.DecodePoint(
+ new X9ECPoint(cFp192v1,
Hex.Decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")),
n, h,
Hex.Decode("3045AE6FC8422f64ED579528D38120EAE12196D5"));
@@ -65,7 +65,7 @@ namespace Org.BouncyCastle.Asn1.X9
return new X9ECParameters(
cFp192v2,
- cFp192v2.DecodePoint(
+ new X9ECPoint(cFp192v2,
Hex.Decode("03eea2bae7e1497842f2de7769cfe9c989c072ad696f48034a")),
n, h,
Hex.Decode("31a92ee2029fd10d901b113e990710f0d21ac6b6"));
@@ -92,7 +92,7 @@ namespace Org.BouncyCastle.Asn1.X9
return new X9ECParameters(
cFp192v3,
- cFp192v3.DecodePoint(
+ new X9ECPoint(cFp192v3,
Hex.Decode("027d29778100c65a1da1783716588dce2b8b4aee8e228f1896")),
n, h,
Hex.Decode("c469684435deb378c4b65ca9591e2a5763059a2e"));
@@ -119,7 +119,7 @@ namespace Org.BouncyCastle.Asn1.X9
return new X9ECParameters(
cFp239v1,
- cFp239v1.DecodePoint(
+ new X9ECPoint(cFp239v1,
Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")),
n, h,
Hex.Decode("e43bb460f0b80cc0c0b075798e948060f8321b7d"));
@@ -146,7 +146,7 @@ namespace Org.BouncyCastle.Asn1.X9
return new X9ECParameters(
cFp239v2,
- cFp239v2.DecodePoint(
+ new X9ECPoint(cFp239v2,
Hex.Decode("0238af09d98727705120c921bb5e9e26296a3cdcf2f35757a0eafd87b830e7")),
n, h,
Hex.Decode("e8b4011604095303ca3b8099982be09fcb9ae616"));
@@ -173,7 +173,7 @@ namespace Org.BouncyCastle.Asn1.X9
return new X9ECParameters(
cFp239v3,
- cFp239v3.DecodePoint(
+ new X9ECPoint(cFp239v3,
Hex.Decode("036768ae8e18bb92cfcf005c949aa2c6d94853d0e660bbf854b1c9505fe95a")),
n, h,
Hex.Decode("7d7374168ffe3471b60a857686a19475d3bfa2ff"));
@@ -200,7 +200,7 @@ namespace Org.BouncyCastle.Asn1.X9
return new X9ECParameters(
cFp256v1,
- cFp256v1.DecodePoint(
+ new X9ECPoint(cFp256v1,
Hex.Decode("036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296")),
n, h,
Hex.Decode("c49d360886e704936a6678e1139d26b7819f7e90"));
@@ -231,7 +231,7 @@ namespace Org.BouncyCastle.Asn1.X9
return new X9ECParameters(
c2m163v1,
- c2m163v1.DecodePoint(
+ new X9ECPoint(c2m163v1,
Hex.Decode("0307AF69989546103D79329FCC3D74880F33BBE803CB")),
n, h,
Hex.Decode("D2C0FB15760860DEF1EEF4D696E6768756151754"));
@@ -259,7 +259,7 @@ namespace Org.BouncyCastle.Asn1.X9
return new X9ECParameters(
c2m163v2,
- c2m163v2.DecodePoint(
+ new X9ECPoint(c2m163v2,
Hex.Decode("030024266E4EB5106D0A964D92C4860E2671DB9B6CC5")),
n, h,
null);
@@ -287,7 +287,7 @@ namespace Org.BouncyCastle.Asn1.X9
return new X9ECParameters(
c2m163v3,
- c2m163v3.DecodePoint(Hex.Decode("0202F9F87B7C574D0BDECF8A22E6524775F98CDEBDCB")),
+ new X9ECPoint(c2m163v3, Hex.Decode("0202F9F87B7C574D0BDECF8A22E6524775F98CDEBDCB")),
n, h,
null);
}
@@ -314,7 +314,7 @@ namespace Org.BouncyCastle.Asn1.X9
return new X9ECParameters(
c2m176w1,
- c2m176w1.DecodePoint(
+ new X9ECPoint(c2m176w1,
Hex.Decode("038D16C2866798B600F9F08BB4A8E860F3298CE04A5798")),
n, h,
null);
@@ -342,7 +342,7 @@ namespace Org.BouncyCastle.Asn1.X9
return new X9ECParameters(
c2m191v1,
- c2m191v1.DecodePoint(
+ new X9ECPoint(c2m191v1,
Hex.Decode("0236B3DAF8A23206F9C4F299D7B21A9C369137F2C84AE1AA0D")),
n, h,
Hex.Decode("4E13CA542744D696E67687561517552F279A8C84"));
@@ -370,7 +370,7 @@ namespace Org.BouncyCastle.Asn1.X9
return new X9ECParameters(
c2m191v2,
- c2m191v2.DecodePoint(
+ new X9ECPoint(c2m191v2,
Hex.Decode("023809B2B7CC1B28CC5A87926AAD83FD28789E81E2C9E3BF10")),
n, h,
null);
@@ -398,7 +398,7 @@ namespace Org.BouncyCastle.Asn1.X9
return new X9ECParameters(
c2m191v3,
- c2m191v3.DecodePoint(
+ new X9ECPoint(c2m191v3,
Hex.Decode("03375D4CE24FDE434489DE8746E71786015009E66E38A926DD")),
n, h,
null);
@@ -426,7 +426,7 @@ namespace Org.BouncyCastle.Asn1.X9
return new X9ECParameters(
c2m208w1,
- c2m208w1.DecodePoint(
+ new X9ECPoint(c2m208w1,
Hex.Decode("0289FDFBE4ABE193DF9559ECF07AC0CE78554E2784EB8C1ED1A57A")),
n, h,
null);
@@ -454,7 +454,7 @@ namespace Org.BouncyCastle.Asn1.X9
return new X9ECParameters(
c2m239v1,
- c2m239v1.DecodePoint(
+ new X9ECPoint(c2m239v1,
Hex.Decode("0257927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D")),
n, h,
null);
@@ -482,7 +482,7 @@ namespace Org.BouncyCastle.Asn1.X9
return new X9ECParameters(
c2m239v2,
- c2m239v2.DecodePoint(
+ new X9ECPoint(c2m239v2,
Hex.Decode("0228F9D04E900069C8DC47A08534FE76D2B900B7D7EF31F5709F200C4CA205")),
n, h,
null);
@@ -510,7 +510,7 @@ namespace Org.BouncyCastle.Asn1.X9
return new X9ECParameters(
c2m239v3,
- c2m239v3.DecodePoint(
+ new X9ECPoint(c2m239v3,
Hex.Decode("0370F6E9D04D289C4E89913CE3530BFDE903977D42B146D539BF1BDE4E9C92")),
n, h,
null);
@@ -538,7 +538,7 @@ namespace Org.BouncyCastle.Asn1.X9
return new X9ECParameters(
c2m272w1,
- c2m272w1.DecodePoint(
+ new X9ECPoint(c2m272w1,
Hex.Decode("026108BABB2CEEBCF787058A056CBE0CFE622D7723A289E08A07AE13EF0D10D171DD8D")),
n, h,
null);
@@ -566,7 +566,7 @@ namespace Org.BouncyCastle.Asn1.X9
return new X9ECParameters(
c2m304w1,
- c2m304w1.DecodePoint(
+ new X9ECPoint(c2m304w1,
Hex.Decode("02197B07845E9BE2D96ADB0F5F3C7F2CFFBD7A3EB8B6FEC35C7FD67F26DDF6285A644F740A2614")),
n, h,
null);
@@ -594,7 +594,7 @@ namespace Org.BouncyCastle.Asn1.X9
return new X9ECParameters(
c2m359v1,
- c2m359v1.DecodePoint(
+ new X9ECPoint(c2m359v1,
Hex.Decode("033C258EF3047767E7EDE0F1FDAA79DAEE3841366A132E163ACED4ED2401DF9C6BDCDE98E8E707C07A2239B1B097")),
n, h,
null);
@@ -622,7 +622,7 @@ namespace Org.BouncyCastle.Asn1.X9
return new X9ECParameters(
c2m368w1,
- c2m368w1.DecodePoint(
+ new X9ECPoint(c2m368w1,
Hex.Decode("021085E2755381DCCCE3C1557AFA10C2F0C0C2825646C5B34A394CBCFA8BC16B22E7E789E927BE216F02E1FB136A5F")),
n, h,
null);
@@ -650,7 +650,7 @@ namespace Org.BouncyCastle.Asn1.X9
return new X9ECParameters(
c2m431r1,
- c2m431r1.DecodePoint(
+ new X9ECPoint(c2m431r1,
Hex.Decode("02120FC05D3C67A99DE161D2F4092622FECA701BE4F50F4758714E8A87BBF2A658EF8C21E7C5EFE965361F6C2999C0C247B0DBD70CE6B7")),
n, h,
null);
diff --git a/crypto/src/asn1/x9/X9ECParameters.cs b/crypto/src/asn1/x9/X9ECParameters.cs
index a192e4c52..2b6b14bcb 100644
--- a/crypto/src/asn1/x9/X9ECParameters.cs
+++ b/crypto/src/asn1/x9/X9ECParameters.cs
@@ -15,7 +15,7 @@ namespace Org.BouncyCastle.Asn1.X9
{
private X9FieldID fieldID;
private ECCurve curve;
- private ECPoint g;
+ private X9ECPoint g;
private BigInteger n;
private BigInteger h;
private byte[] seed;
@@ -29,36 +29,28 @@ namespace Org.BouncyCastle.Asn1.X9
throw new ArgumentException("bad version in X9ECParameters");
}
- X9Curve x9c = null;
- if (seq[2] is X9Curve)
- {
- x9c = (X9Curve) seq[2];
- }
- else
- {
- x9c = new X9Curve(
- new X9FieldID(
- (Asn1Sequence) seq[1]),
- (Asn1Sequence) seq[2]);
- }
+ X9Curve x9c = new X9Curve(
+ X9FieldID.GetInstance(seq[1]),
+ Asn1Sequence.GetInstance(seq[2]));
this.curve = x9c.Curve;
+ object p = seq[3];
- if (seq[3] is X9ECPoint)
+ if (p is X9ECPoint)
{
- this.g = ((X9ECPoint) seq[3]).Point;
+ this.g = ((X9ECPoint)p);
}
else
{
- this.g = new X9ECPoint(curve, (Asn1OctetString) seq[3]).Point;
+ this.g = new X9ECPoint(curve, (Asn1OctetString)p);
}
- this.n = ((DerInteger) seq[4]).Value;
+ this.n = ((DerInteger)seq[4]).Value;
this.seed = x9c.GetSeed();
if (seq.Count == 6)
{
- this.h = ((DerInteger) seq[5]).Value;
+ this.h = ((DerInteger)seq[5]).Value;
}
}
@@ -66,7 +58,16 @@ namespace Org.BouncyCastle.Asn1.X9
ECCurve curve,
ECPoint g,
BigInteger n)
- : this(curve, g, n, BigInteger.One, null)
+ : this(curve, g, n, null, null)
+ {
+ }
+
+ public X9ECParameters(
+ ECCurve curve,
+ X9ECPoint g,
+ BigInteger n,
+ BigInteger h)
+ : this(curve, g, n, h, null)
{
}
@@ -85,9 +86,19 @@ namespace Org.BouncyCastle.Asn1.X9
BigInteger n,
BigInteger h,
byte[] seed)
+ : this(curve, new X9ECPoint(g), n, h, seed)
+ {
+ }
+
+ public X9ECParameters(
+ ECCurve curve,
+ X9ECPoint g,
+ BigInteger n,
+ BigInteger h,
+ byte[] seed)
{
this.curve = curve;
- this.g = g.Normalize();
+ this.g = g;
this.n = n;
this.h = h;
this.seed = seed;
@@ -126,7 +137,7 @@ namespace Org.BouncyCastle.Asn1.X9
public ECPoint G
{
- get { return g; }
+ get { return g.Point; }
}
public BigInteger N
@@ -136,16 +147,7 @@ namespace Org.BouncyCastle.Asn1.X9
public BigInteger H
{
- get
- {
- if (h == null)
- {
- // TODO - this should be calculated, it will cause issues with custom curves.
- return BigInteger.One;
- }
-
- return h;
- }
+ get { return h; }
}
public byte[] GetSeed()
@@ -154,6 +156,36 @@ namespace Org.BouncyCastle.Asn1.X9
}
/**
+ * Return the ASN.1 entry representing the Curve.
+ *
+ * @return the X9Curve for the curve in these parameters.
+ */
+ public X9Curve CurveEntry
+ {
+ get { return new X9Curve(curve, seed); }
+ }
+
+ /**
+ * Return the ASN.1 entry representing the FieldID.
+ *
+ * @return the X9FieldID for the FieldID in these parameters.
+ */
+ public X9FieldID FieldIDEntry
+ {
+ get { return fieldID; }
+ }
+
+ /**
+ * Return the ASN.1 entry representing the base point G.
+ *
+ * @return the X9ECPoint for the base point in these parameters.
+ */
+ public X9ECPoint BaseEntry
+ {
+ get { return g; }
+ }
+
+ /**
* Produce an object suitable for an Asn1OutputStream.
* <pre>
* ECParameters ::= Sequence {
@@ -169,10 +201,10 @@ namespace Org.BouncyCastle.Asn1.X9
public override Asn1Object ToAsn1Object()
{
Asn1EncodableVector v = new Asn1EncodableVector(
- new DerInteger(1),
+ new DerInteger(BigInteger.One),
fieldID,
new X9Curve(curve, seed),
- new X9ECPoint(g),
+ g,
new DerInteger(n));
if (h != null)
diff --git a/crypto/src/asn1/x9/X9ECPoint.cs b/crypto/src/asn1/x9/X9ECPoint.cs
index 75d58cd38..7ef4f13bc 100644
--- a/crypto/src/asn1/x9/X9ECPoint.cs
+++ b/crypto/src/asn1/x9/X9ECPoint.cs
@@ -1,5 +1,7 @@
using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Utilities;
+
namespace Org.BouncyCastle.Asn1.X9
{
/**
@@ -8,24 +10,58 @@ namespace Org.BouncyCastle.Asn1.X9
public class X9ECPoint
: Asn1Encodable
{
- private readonly ECPoint p;
+ private readonly Asn1OctetString encoding;
+
+ private ECCurve c;
+ private ECPoint p;
+
+ public X9ECPoint(ECPoint p)
+ : this(p, false)
+ {
+ }
- public X9ECPoint(
- ECPoint p)
+ public X9ECPoint(ECPoint p, bool compressed)
{
this.p = p.Normalize();
+ this.encoding = new DerOctetString(p.GetEncoded(compressed));
+ }
+
+ public X9ECPoint(ECCurve c, byte[] encoding)
+ {
+ this.c = c;
+ this.encoding = new DerOctetString(Arrays.Clone(encoding));
}
- public X9ECPoint(
- ECCurve c,
- Asn1OctetString s)
+ public X9ECPoint(ECCurve c, Asn1OctetString s)
+ : this(c, s.GetOctets())
{
- this.p = c.DecodePoint(s.GetOctets());
+ }
+
+ public byte[] GetPointEncoding()
+ {
+ return Arrays.Clone(encoding.GetOctets());
}
public ECPoint Point
{
- get { return p; }
+ get
+ {
+ if (p == null)
+ {
+ p = c.DecodePoint(encoding.GetOctets()).Normalize();
+ }
+
+ return p;
+ }
+ }
+
+ public bool IsPointCompressed
+ {
+ get
+ {
+ byte[] octets = encoding.GetOctets();
+ return octets != null && octets.Length > 0 && (octets[0] == 2 || octets[0] == 3);
+ }
}
/**
@@ -38,7 +74,7 @@ namespace Org.BouncyCastle.Asn1.X9
*/
public override Asn1Object ToAsn1Object()
{
- return new DerOctetString(p.GetEncoded());
+ return encoding;
}
}
}
diff --git a/crypto/src/asn1/x9/X9FieldID.cs b/crypto/src/asn1/x9/X9FieldID.cs
index 58823a285..08d7d71b4 100644
--- a/crypto/src/asn1/x9/X9FieldID.cs
+++ b/crypto/src/asn1/x9/X9FieldID.cs
@@ -90,11 +90,19 @@ namespace Org.BouncyCastle.Asn1.X9
this.parameters = new DerSequence(fieldIdParams);
}
- internal X9FieldID(
- Asn1Sequence seq)
+ private X9FieldID(Asn1Sequence seq)
{
- this.id = (DerObjectIdentifier) seq[0];
- this.parameters = (Asn1Object) seq[1];
+ this.id = DerObjectIdentifier.GetInstance(seq[0]);
+ this.parameters = seq[1].ToAsn1Object();
+ }
+
+ public static X9FieldID GetInstance(object obj)
+ {
+ if (obj is X9FieldID)
+ return (X9FieldID)obj;
+ if (obj == null)
+ return null;
+ return new X9FieldID(Asn1Sequence.GetInstance(obj));
}
public DerObjectIdentifier Identifier
diff --git a/crypto/src/bcpg/ArmoredOutputStream.cs b/crypto/src/bcpg/ArmoredOutputStream.cs
index b3a32c6f5..5d4b6b5a7 100644
--- a/crypto/src/bcpg/ArmoredOutputStream.cs
+++ b/crypto/src/bcpg/ArmoredOutputStream.cs
@@ -36,46 +36,46 @@ namespace Org.BouncyCastle.Bcpg
* encode the input data producing a base 64 encoded byte array.
*/
private static void Encode(
- Stream outStream,
- int[] data,
- int len)
+ Stream outStream,
+ int[] data,
+ int len)
{
- Debug.Assert(len > 0);
- Debug.Assert(len < 4);
+ Debug.Assert(len > 0);
+ Debug.Assert(len < 4);
- byte[] bs = new byte[4];
- int d1 = data[0];
- bs[0] = encodingTable[(d1 >> 2) & 0x3f];
+ byte[] bs = new byte[4];
+ int d1 = data[0];
+ bs[0] = encodingTable[(d1 >> 2) & 0x3f];
- switch (len)
+ switch (len)
{
- case 1:
- {
- bs[1] = encodingTable[(d1 << 4) & 0x3f];
- bs[2] = (byte)'=';
- bs[3] = (byte)'=';
- break;
- }
- case 2:
- {
- int d2 = data[1];
- bs[1] = encodingTable[((d1 << 4) | (d2 >> 4)) & 0x3f];
- bs[2] = encodingTable[(d2 << 2) & 0x3f];
- bs[3] = (byte)'=';
- break;
- }
- case 3:
- {
- int d2 = data[1];
- int d3 = data[2];
- bs[1] = encodingTable[((d1 << 4) | (d2 >> 4)) & 0x3f];
- bs[2] = encodingTable[((d2 << 2) | (d3 >> 6)) & 0x3f];
- bs[3] = encodingTable[d3 & 0x3f];
- break;
- }
+ case 1:
+ {
+ bs[1] = encodingTable[(d1 << 4) & 0x3f];
+ bs[2] = (byte)'=';
+ bs[3] = (byte)'=';
+ break;
+ }
+ case 2:
+ {
+ int d2 = data[1];
+ bs[1] = encodingTable[((d1 << 4) | (d2 >> 4)) & 0x3f];
+ bs[2] = encodingTable[(d2 << 2) & 0x3f];
+ bs[3] = (byte)'=';
+ break;
+ }
+ case 3:
+ {
+ int d2 = data[1];
+ int d3 = data[2];
+ bs[1] = encodingTable[((d1 << 4) | (d2 >> 4)) & 0x3f];
+ bs[2] = encodingTable[((d2 << 2) | (d3 >> 6)) & 0x3f];
+ bs[3] = encodingTable[d3 & 0x3f];
+ break;
+ }
}
- outStream.Write(bs, 0, bs.Length);
+ outStream.Write(bs, 0, bs.Length);
}
private readonly Stream outStream;
@@ -91,18 +91,18 @@ namespace Org.BouncyCastle.Bcpg
private string type;
- private static readonly string nl = Platform.NewLine;
- private static readonly string headerStart = "-----BEGIN PGP ";
- private static readonly string headerTail = "-----";
- private static readonly string footerStart = "-----END PGP ";
- private static readonly string footerTail = "-----";
+ private static readonly string nl = Platform.NewLine;
+ private static readonly string headerStart = "-----BEGIN PGP ";
+ private static readonly string headerTail = "-----";
+ private static readonly string footerStart = "-----END PGP ";
+ private static readonly string footerTail = "-----";
private static readonly string version = "BCPG C# v"
- + Assembly.GetExecutingAssembly().GetName().Version;
+ + Assembly.GetExecutingAssembly().GetName().Version;
- private readonly IDictionary headers;
+ private readonly IDictionary headers;
- public ArmoredOutputStream(Stream outStream)
+ public ArmoredOutputStream(Stream outStream)
{
this.outStream = outStream;
this.headers = Platform.CreateHashtable();
@@ -174,10 +174,10 @@ namespace Org.BouncyCastle.Bcpg
throw new IOException("unknown hash algorithm tag in beginClearText: " + hashAlgorithm);
}
- DoWrite("-----BEGIN PGP SIGNED MESSAGE-----" + nl);
+ DoWrite("-----BEGIN PGP SIGNED MESSAGE-----" + nl);
DoWrite("Hash: " + hash + nl + nl);
- clearText = true;
+ clearText = true;
newLine = true;
lastb = 0;
}
@@ -218,7 +218,7 @@ namespace Org.BouncyCastle.Bcpg
{
bool newPacket = (b & 0x40) != 0;
- int tag;
+ int tag;
if (newPacket)
{
tag = b & 0x3f;
@@ -241,7 +241,7 @@ namespace Org.BouncyCastle.Bcpg
break;
default:
type = "MESSAGE";
- break;
+ break;
}
DoWrite(headerStart + type + headerTail + nl);
@@ -277,23 +277,23 @@ namespace Org.BouncyCastle.Bcpg
}
/**
- * <b>Note</b>: close does nor close the underlying stream. So it is possible to write
+ * <b>Note</b>: Close() does not close the underlying stream. So it is possible to write
* multiple objects using armoring to a single stream.
*/
public override void Close()
{
if (type != null)
{
- if (bufPtr > 0)
- {
- Encode(outStream, buf, bufPtr);
- }
+ if (bufPtr > 0)
+ {
+ Encode(outStream, buf, bufPtr);
+ }
DoWrite(nl + '=');
int crcV = crc.Value;
- buf[0] = ((crcV >> 16) & 0xff);
+ buf[0] = ((crcV >> 16) & 0xff);
buf[1] = ((crcV >> 8) & 0xff);
buf[2] = (crcV & 0xff);
@@ -309,22 +309,22 @@ namespace Org.BouncyCastle.Bcpg
type = null;
start = true;
- base.Close();
- }
+ base.Close();
+ }
}
- private void WriteHeaderEntry(
- string name,
- string v)
+ private void WriteHeaderEntry(
+ string name,
+ string v)
{
DoWrite(name + ": " + v + nl);
}
- private void DoWrite(
- string s)
+ private void DoWrite(
+ string s)
{
byte[] bs = Strings.ToAsciiByteArray(s);
- outStream.Write(bs, 0, bs.Length);
+ outStream.Write(bs, 0, bs.Length);
}
}
}
diff --git a/crypto/src/bcpg/ECDHPublicBCPGKey.cs b/crypto/src/bcpg/ECDHPublicBCPGKey.cs
index b85379586..dc225e31e 100644
--- a/crypto/src/bcpg/ECDHPublicBCPGKey.cs
+++ b/crypto/src/bcpg/ECDHPublicBCPGKey.cs
@@ -10,8 +10,8 @@ namespace Org.BouncyCastle.Bcpg
: ECPublicBcpgKey
{
private byte reserved;
- private byte hashFunctionId;
- private byte symAlgorithmId;
+ private HashAlgorithmTag hashFunctionId;
+ private SymmetricKeyAlgorithmTag symAlgorithmId;
/// <param name="bcpgIn">The stream to read the packet from.</param>
public ECDHPublicBcpgKey(
@@ -26,8 +26,8 @@ namespace Org.BouncyCastle.Bcpg
bcpgIn.ReadFully(kdfParameters);
reserved = kdfParameters[0];
- hashFunctionId = kdfParameters[1];
- symAlgorithmId = kdfParameters[2];
+ hashFunctionId = (HashAlgorithmTag)kdfParameters[1];
+ symAlgorithmId = (SymmetricKeyAlgorithmTag)kdfParameters[2];
VerifyHashAlgorithm();
VerifySymmetricKeyAlgorithm();
@@ -36,13 +36,13 @@ namespace Org.BouncyCastle.Bcpg
public ECDHPublicBcpgKey(
DerObjectIdentifier oid,
ECPoint point,
- int hashAlgorithm,
- int symmetricKeyAlgorithm)
+ HashAlgorithmTag hashAlgorithm,
+ SymmetricKeyAlgorithmTag symmetricKeyAlgorithm)
: base(oid, point)
{
reserved = 1;
- hashFunctionId = (byte)hashAlgorithm;
- symAlgorithmId = (byte)symmetricKeyAlgorithm;
+ hashFunctionId = hashAlgorithm;
+ symAlgorithmId = symmetricKeyAlgorithm;
VerifyHashAlgorithm();
VerifySymmetricKeyAlgorithm();
@@ -53,12 +53,12 @@ namespace Org.BouncyCastle.Bcpg
get { return reserved; }
}
- public virtual byte HashAlgorithm
+ public virtual HashAlgorithmTag HashAlgorithm
{
get { return hashFunctionId; }
}
- public virtual byte SymmetricKeyAlgorithm
+ public virtual SymmetricKeyAlgorithmTag SymmetricKeyAlgorithm
{
get { return symAlgorithmId; }
}
@@ -69,8 +69,8 @@ namespace Org.BouncyCastle.Bcpg
base.Encode(bcpgOut);
bcpgOut.WriteByte(0x3);
bcpgOut.WriteByte(reserved);
- bcpgOut.WriteByte(hashFunctionId);
- bcpgOut.WriteByte(symAlgorithmId);
+ bcpgOut.WriteByte((byte)hashFunctionId);
+ bcpgOut.WriteByte((byte)symAlgorithmId);
}
private void VerifyHashAlgorithm()
diff --git a/crypto/src/bcpg/PublicKeyAlgorithmTags.cs b/crypto/src/bcpg/PublicKeyAlgorithmTags.cs
index 4a6704c14..9e30b54f7 100644
--- a/crypto/src/bcpg/PublicKeyAlgorithmTags.cs
+++ b/crypto/src/bcpg/PublicKeyAlgorithmTags.cs
@@ -1,3 +1,5 @@
+using System;
+
namespace Org.BouncyCastle.Bcpg
{
/// <remarks>Public Key Algorithm tag numbers.</remarks>
@@ -8,6 +10,7 @@ namespace Org.BouncyCastle.Bcpg
RsaSign = 3, // RSA Sign-Only
ElGamalEncrypt = 16, // Elgamal (Encrypt-Only), see [ELGAMAL]
Dsa = 17, // DSA (Digital Signature Standard)
+ [Obsolete("Use 'ECDH' instead")]
EC = 18, // Reserved for Elliptic Curve
ECDH = 18, // Reserved for Elliptic Curve (actual algorithm name)
ECDsa = 19, // Reserved for ECDSA
diff --git a/crypto/src/bcpg/PublicKeyEncSessionPacket.cs b/crypto/src/bcpg/PublicKeyEncSessionPacket.cs
index d10605f1d..74d04f7aa 100644
--- a/crypto/src/bcpg/PublicKeyEncSessionPacket.cs
+++ b/crypto/src/bcpg/PublicKeyEncSessionPacket.cs
@@ -2,6 +2,8 @@ using System;
using System.IO;
using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Bcpg
{
@@ -12,7 +14,7 @@ namespace Org.BouncyCastle.Bcpg
private int version;
private long keyId;
private PublicKeyAlgorithmTag algorithm;
- private BigInteger[] data;
+ private byte[][] data;
internal PublicKeyEncSessionPacket(
BcpgInputStream bcpgIn)
@@ -34,33 +36,41 @@ namespace Org.BouncyCastle.Bcpg
{
case PublicKeyAlgorithmTag.RsaEncrypt:
case PublicKeyAlgorithmTag.RsaGeneral:
- data = new BigInteger[]{ new MPInteger(bcpgIn).Value };
+ data = new byte[][]{ new MPInteger(bcpgIn).GetEncoded() };
break;
case PublicKeyAlgorithmTag.ElGamalEncrypt:
case PublicKeyAlgorithmTag.ElGamalGeneral:
- data = new BigInteger[]
- {
- new MPInteger(bcpgIn).Value,
- new MPInteger(bcpgIn).Value
- };
+ MPInteger p = new MPInteger(bcpgIn);
+ MPInteger g = new MPInteger(bcpgIn);
+ data = new byte[][]{
+ p.GetEncoded(),
+ g.GetEncoded(),
+ };
break;
+ case PublicKeyAlgorithmTag.ECDH:
+ data = new byte[][]{ Streams.ReadAll(bcpgIn) };
+ break;
default:
throw new IOException("unknown PGP public key algorithm encountered");
}
}
- public PublicKeyEncSessionPacket(
- long keyId,
- PublicKeyAlgorithmTag algorithm,
- BigInteger[] data)
+ public PublicKeyEncSessionPacket(
+ long keyId,
+ PublicKeyAlgorithmTag algorithm,
+ byte[][] data)
{
this.version = 3;
this.keyId = keyId;
this.algorithm = algorithm;
- this.data = (BigInteger[]) data.Clone();
+ this.data = new byte[data.Length][];
+ for (int i = 0; i < data.Length; ++i)
+ {
+ this.data[i] = Arrays.Clone(data[i]);
+ }
}
- public int Version
+ public int Version
{
get { return version; }
}
@@ -75,12 +85,12 @@ namespace Org.BouncyCastle.Bcpg
get { return algorithm; }
}
- public BigInteger[] GetEncSessionKey()
+ public byte[][] GetEncSessionKey()
{
- return (BigInteger[]) data.Clone();
+ return data;
}
- public override void Encode(
+ public override void Encode(
BcpgOutputStream bcpgOut)
{
MemoryStream bOut = new MemoryStream();
@@ -92,12 +102,14 @@ namespace Org.BouncyCastle.Bcpg
pOut.WriteByte((byte)algorithm);
- for (int i = 0; i != data.Length; i++)
- {
- MPInteger.Encode(pOut, data[i]);
- }
+ for (int i = 0; i < data.Length; ++i)
+ {
+ pOut.Write(data[i]);
+ }
+
+ pOut.Close();
- bcpgOut.WritePacket(PacketTag.PublicKeyEncryptedSession , bOut.ToArray(), true);
+ bcpgOut.WritePacket(PacketTag.PublicKeyEncryptedSession , bOut.ToArray(), true);
}
}
}
diff --git a/crypto/src/bcpg/PublicKeyPacket.cs b/crypto/src/bcpg/PublicKeyPacket.cs
index cea5c8ed2..bbed941dc 100644
--- a/crypto/src/bcpg/PublicKeyPacket.cs
+++ b/crypto/src/bcpg/PublicKeyPacket.cs
@@ -44,7 +44,7 @@ namespace Org.BouncyCastle.Bcpg
case PublicKeyAlgorithmTag.ElGamalGeneral:
key = new ElGamalPublicBcpgKey(bcpgIn);
break;
- case PublicKeyAlgorithmTag.EC:
+ case PublicKeyAlgorithmTag.ECDH:
key = new ECDHPublicBcpgKey(bcpgIn);
break;
case PublicKeyAlgorithmTag.ECDsa:
diff --git a/crypto/src/bcpg/S2k.cs b/crypto/src/bcpg/S2k.cs
index f6d306890..33fd792fe 100644
--- a/crypto/src/bcpg/S2k.cs
+++ b/crypto/src/bcpg/S2k.cs
@@ -84,19 +84,19 @@ namespace Org.BouncyCastle.Bcpg
this.itCount = itCount;
}
- public int Type
+ public virtual int Type
{
get { return type; }
}
/// <summary>The hash algorithm.</summary>
- public HashAlgorithmTag HashAlgorithm
+ public virtual HashAlgorithmTag HashAlgorithm
{
get { return algorithm; }
}
/// <summary>The IV for the key generation algorithm.</summary>
- public byte[] GetIV()
+ public virtual byte[] GetIV()
{
return Arrays.Clone(iv);
}
@@ -108,13 +108,13 @@ namespace Org.BouncyCastle.Bcpg
}
/// <summary>The iteration count</summary>
- public long IterationCount
+ public virtual long IterationCount
{
get { return (16 + (itCount & 15)) << ((itCount >> 4) + ExpBias); }
}
/// <summary>The protection mode - only if GnuDummyS2K</summary>
- public int ProtectionMode
+ public virtual int ProtectionMode
{
get { return protectionMode; }
}
diff --git a/crypto/src/bcpg/SignatureSubpacket.cs b/crypto/src/bcpg/SignatureSubpacket.cs
index ac26f8a3c..d99315599 100644
--- a/crypto/src/bcpg/SignatureSubpacket.cs
+++ b/crypto/src/bcpg/SignatureSubpacket.cs
@@ -7,20 +7,22 @@ namespace Org.BouncyCastle.Bcpg
{
private readonly SignatureSubpacketTag type;
private readonly bool critical;
-
- internal readonly byte[] data;
+ private readonly bool isLongLength;
+ internal byte[] data;
protected internal SignatureSubpacket(
SignatureSubpacketTag type,
bool critical,
+ bool isLongLength,
byte[] data)
{
this.type = type;
this.critical = critical;
+ this.isLongLength = isLongLength;
this.data = data;
}
- public SignatureSubpacketTag SubpacketType
+ public SignatureSubpacketTag SubpacketType
{
get { return type; }
}
@@ -30,7 +32,12 @@ namespace Org.BouncyCastle.Bcpg
return critical;
}
- /// <summary>Return the generic data making up the packet.</summary>
+ public bool IsLongLength()
+ {
+ return isLongLength;
+ }
+
+ /// <summary>Return the generic data making up the packet.</summary>
public byte[] GetData()
{
return (byte[]) data.Clone();
@@ -41,18 +48,7 @@ namespace Org.BouncyCastle.Bcpg
{
int bodyLen = data.Length + 1;
- if (bodyLen < 192)
- {
- os.WriteByte((byte)bodyLen);
- }
- else if (bodyLen <= 8383)
- {
- bodyLen -= 192;
-
- os.WriteByte((byte)(((bodyLen >> 8) & 0xff) + 192));
- os.WriteByte((byte)bodyLen);
- }
- else
+ if (isLongLength)
{
os.WriteByte(0xff);
os.WriteByte((byte)(bodyLen >> 24));
@@ -60,6 +56,28 @@ namespace Org.BouncyCastle.Bcpg
os.WriteByte((byte)(bodyLen >> 8));
os.WriteByte((byte)bodyLen);
}
+ else
+ {
+ if (bodyLen < 192)
+ {
+ os.WriteByte((byte)bodyLen);
+ }
+ else if (bodyLen <= 8383)
+ {
+ bodyLen -= 192;
+
+ os.WriteByte((byte)(((bodyLen >> 8) & 0xff) + 192));
+ os.WriteByte((byte)bodyLen);
+ }
+ else
+ {
+ os.WriteByte(0xff);
+ os.WriteByte((byte)(bodyLen >> 24));
+ os.WriteByte((byte)(bodyLen >> 16));
+ os.WriteByte((byte)(bodyLen >> 8));
+ os.WriteByte((byte)bodyLen);
+ }
+ }
if (critical)
{
diff --git a/crypto/src/bcpg/SignatureSubpacketsReader.cs b/crypto/src/bcpg/SignatureSubpacketsReader.cs
index 8dd1af332..80bedb07c 100644
--- a/crypto/src/bcpg/SignatureSubpacketsReader.cs
+++ b/crypto/src/bcpg/SignatureSubpacketsReader.cs
@@ -1,6 +1,8 @@
using System;
using System.IO;
+
using Org.BouncyCastle.Bcpg.Sig;
+using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Bcpg
@@ -25,7 +27,9 @@ namespace Org.BouncyCastle.Bcpg
return null;
int bodyLen = 0;
- if (l < 192)
+ bool isLongLength = false;
+
+ if (l < 192)
{
bodyLen = l;
}
@@ -35,54 +39,90 @@ namespace Org.BouncyCastle.Bcpg
}
else if (l == 255)
{
+ isLongLength = true;
bodyLen = (input.ReadByte() << 24) | (input.ReadByte() << 16)
| (input.ReadByte() << 8) | input.ReadByte();
}
else
{
- // TODO Error?
+ throw new IOException("unexpected length header");
}
- int tag = input.ReadByte();
+ int tag = input.ReadByte();
if (tag < 0)
throw new EndOfStreamException("unexpected EOF reading signature sub packet");
- byte[] data = new byte[bodyLen - 1];
- if (Streams.ReadFully(input, data) < data.Length)
- throw new EndOfStreamException();
+ byte[] data = new byte[bodyLen - 1];
+
+ //
+ // this may seem a bit strange but it turns out some applications miscode the length
+ // in fixed length fields, so we check the length we do get, only throwing an exception if
+ // we really cannot continue
+ //
+ int bytesRead = Streams.ReadFully(input, data);
+
+ bool isCritical = ((tag & 0x80) != 0);
+ SignatureSubpacketTag type = (SignatureSubpacketTag)(tag & 0x7f);
- bool isCritical = ((tag & 0x80) != 0);
- SignatureSubpacketTag type = (SignatureSubpacketTag)(tag & 0x7f);
- switch (type)
+ if (bytesRead != data.Length)
+ {
+ switch (type)
+ {
+ case SignatureSubpacketTag.CreationTime:
+ data = CheckData(data, 4, bytesRead, "Signature Creation Time");
+ break;
+ case SignatureSubpacketTag.IssuerKeyId:
+ data = CheckData(data, 8, bytesRead, "Issuer");
+ break;
+ case SignatureSubpacketTag.KeyExpireTime:
+ data = CheckData(data, 4, bytesRead, "Signature Key Expiration Time");
+ break;
+ case SignatureSubpacketTag.ExpireTime:
+ data = CheckData(data, 4, bytesRead, "Signature Expiration Time");
+ break;
+ default:
+ throw new EndOfStreamException("truncated subpacket data.");
+ }
+ }
+
+ switch (type)
{
case SignatureSubpacketTag.CreationTime:
- return new SignatureCreationTime(isCritical, data);
+ return new SignatureCreationTime(isCritical, isLongLength, data);
case SignatureSubpacketTag.KeyExpireTime:
- return new KeyExpirationTime(isCritical, data);
+ return new KeyExpirationTime(isCritical, isLongLength, data);
case SignatureSubpacketTag.ExpireTime:
- return new SignatureExpirationTime(isCritical, data);
+ return new SignatureExpirationTime(isCritical, isLongLength, data);
case SignatureSubpacketTag.Revocable:
- return new Revocable(isCritical, data);
+ return new Revocable(isCritical, isLongLength, data);
case SignatureSubpacketTag.Exportable:
- return new Exportable(isCritical, data);
+ return new Exportable(isCritical, isLongLength, data);
case SignatureSubpacketTag.IssuerKeyId:
- return new IssuerKeyId(isCritical, data);
+ return new IssuerKeyId(isCritical, isLongLength, data);
case SignatureSubpacketTag.TrustSig:
- return new TrustSignature(isCritical, data);
+ return new TrustSignature(isCritical, isLongLength, data);
case SignatureSubpacketTag.PreferredCompressionAlgorithms:
case SignatureSubpacketTag.PreferredHashAlgorithms:
case SignatureSubpacketTag.PreferredSymmetricAlgorithms:
- return new PreferredAlgorithms(type, isCritical, data);
+ return new PreferredAlgorithms(type, isCritical, isLongLength, data);
case SignatureSubpacketTag.KeyFlags:
- return new KeyFlags(isCritical, data);
+ return new KeyFlags(isCritical, isLongLength, data);
case SignatureSubpacketTag.PrimaryUserId:
- return new PrimaryUserId(isCritical, data);
+ return new PrimaryUserId(isCritical, isLongLength, data);
case SignatureSubpacketTag.SignerUserId:
- return new SignerUserId(isCritical, data);
+ return new SignerUserId(isCritical, isLongLength, data);
case SignatureSubpacketTag.NotationData:
- return new NotationData(isCritical, data);
+ return new NotationData(isCritical, isLongLength, data);
}
- return new SignatureSubpacket(type, isCritical, data);
+ return new SignatureSubpacket(type, isCritical, isLongLength, data);
}
+
+ private byte[] CheckData(byte[] data, int expected, int bytesRead, string name)
+ {
+ if (bytesRead != expected)
+ throw new EndOfStreamException("truncated " + name + " subpacket data.");
+
+ return Arrays.CopyOfRange(data, 0, expected);
+ }
}
}
diff --git a/crypto/src/bcpg/sig/EmbeddedSignature.cs b/crypto/src/bcpg/sig/EmbeddedSignature.cs
index e47604ac8..fffdaef73 100644
--- a/crypto/src/bcpg/sig/EmbeddedSignature.cs
+++ b/crypto/src/bcpg/sig/EmbeddedSignature.cs
@@ -10,8 +10,9 @@ namespace Org.BouncyCastle.Bcpg.Sig
{
public EmbeddedSignature(
bool critical,
+ bool isLongLength,
byte[] data)
- : base(SignatureSubpacketTag.EmbeddedSignature, critical, data)
+ : base(SignatureSubpacketTag.EmbeddedSignature, critical, isLongLength, data)
{
}
}
diff --git a/crypto/src/bcpg/sig/Exportable.cs b/crypto/src/bcpg/sig/Exportable.cs
index 4455c3814..4d030346f 100644
--- a/crypto/src/bcpg/sig/Exportable.cs
+++ b/crypto/src/bcpg/sig/Exportable.cs
@@ -1,7 +1,5 @@
using System;
-
-
namespace Org.BouncyCastle.Bcpg.Sig
{
/**
@@ -27,15 +25,16 @@ namespace Org.BouncyCastle.Bcpg.Sig
public Exportable(
bool critical,
- byte[] data)
- : base(SignatureSubpacketTag.Exportable, critical, data)
+ bool isLongLength,
+ byte[] data)
+ : base(SignatureSubpacketTag.Exportable, critical, isLongLength, data)
{
}
public Exportable(
bool critical,
bool isExportable)
- : base(SignatureSubpacketTag.Exportable, critical, BooleanToByteArray(isExportable))
+ : base(SignatureSubpacketTag.Exportable, critical, false, BooleanToByteArray(isExportable))
{
}
diff --git a/crypto/src/bcpg/sig/Features.cs b/crypto/src/bcpg/sig/Features.cs
new file mode 100644
index 000000000..29584239a
--- /dev/null
+++ b/crypto/src/bcpg/sig/Features.cs
@@ -0,0 +1,75 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Bcpg.Sig
+{
+ /**
+ * packet giving signature expiration time.
+ */
+ public class Features
+ : SignatureSubpacket
+ {
+ /** Identifier for the modification detection feature */
+ public static readonly byte FEATURE_MODIFICATION_DETECTION = 1;
+
+ private static byte[] FeatureToByteArray(byte feature)
+ {
+ return new byte[]{ feature };
+ }
+
+ public Features(
+ bool critical,
+ bool isLongLength,
+ byte[] data)
+ : base(SignatureSubpacketTag.Features, critical, isLongLength, data)
+ {
+ }
+
+ public Features(bool critical, byte feature)
+ : base(SignatureSubpacketTag.Features, critical, false, FeatureToByteArray(feature))
+ {
+ }
+
+ /**
+ * Returns if modification detection is supported.
+ */
+ public bool SupportsModificationDetection
+ {
+ get { return SupportsFeature(FEATURE_MODIFICATION_DETECTION); }
+ }
+
+ /**
+ * Returns if a particular feature is supported.
+ */
+ public bool SupportsFeature(byte feature)
+ {
+ return Array.IndexOf(data, feature) >= 0;
+ }
+
+ /**
+ * Sets support for a particular feature.
+ */
+ private void SetSupportsFeature(byte feature, bool support)
+ {
+ if (feature == 0)
+ throw new ArgumentException("cannot be 0", "feature");
+
+ int i = Array.IndexOf(data, feature);
+ if ((i >= 0) == support)
+ return;
+
+ if (support)
+ {
+ data = Arrays.Append(data, feature);
+ }
+ else
+ {
+ byte[] temp = new byte[data.Length - 1];
+ Array.Copy(data, 0, temp, 0, i);
+ Array.Copy(data, i + 1, temp, i, temp.Length - i);
+ data = temp;
+ }
+ }
+ }
+}
diff --git a/crypto/src/bcpg/sig/IssuerKeyId.cs b/crypto/src/bcpg/sig/IssuerKeyId.cs
index 91490d33b..627ea3ecf 100644
--- a/crypto/src/bcpg/sig/IssuerKeyId.cs
+++ b/crypto/src/bcpg/sig/IssuerKeyId.cs
@@ -29,15 +29,16 @@ namespace Org.BouncyCastle.Bcpg.Sig
public IssuerKeyId(
bool critical,
- byte[] data)
- : base(SignatureSubpacketTag.IssuerKeyId, critical, data)
+ bool isLongLength,
+ byte[] data)
+ : base(SignatureSubpacketTag.IssuerKeyId, critical, isLongLength, data)
{
}
public IssuerKeyId(
bool critical,
- long keyId)
- : base(SignatureSubpacketTag.IssuerKeyId, critical, KeyIdToBytes(keyId))
+ long keyId)
+ : base(SignatureSubpacketTag.IssuerKeyId, critical, false, KeyIdToBytes(keyId))
{
}
diff --git a/crypto/src/bcpg/sig/KeyExpirationTime.cs b/crypto/src/bcpg/sig/KeyExpirationTime.cs
index 23b4cac29..dfd3e76fd 100644
--- a/crypto/src/bcpg/sig/KeyExpirationTime.cs
+++ b/crypto/src/bcpg/sig/KeyExpirationTime.cs
@@ -1,7 +1,5 @@
using System;
-
-
namespace Org.BouncyCastle.Bcpg.Sig
{
/**
@@ -25,15 +23,16 @@ namespace Org.BouncyCastle.Bcpg.Sig
public KeyExpirationTime(
bool critical,
- byte[] data)
- : base(SignatureSubpacketTag.KeyExpireTime, critical, data)
+ bool isLongLength,
+ byte[] data)
+ : base(SignatureSubpacketTag.KeyExpireTime, critical, isLongLength, data)
{
}
public KeyExpirationTime(
bool critical,
- long seconds)
- : base(SignatureSubpacketTag.KeyExpireTime, critical, TimeToBytes(seconds))
+ long seconds)
+ : base(SignatureSubpacketTag.KeyExpireTime, critical, false, TimeToBytes(seconds))
{
}
diff --git a/crypto/src/bcpg/sig/KeyFlags.cs b/crypto/src/bcpg/sig/KeyFlags.cs
index 0592301b3..5b5d85a72 100644
--- a/crypto/src/bcpg/sig/KeyFlags.cs
+++ b/crypto/src/bcpg/sig/KeyFlags.cs
@@ -40,15 +40,16 @@ namespace Org.BouncyCastle.Bcpg.Sig
public KeyFlags(
bool critical,
- byte[] data)
- : base(SignatureSubpacketTag.KeyFlags, critical, data)
+ bool isLongLength,
+ byte[] data)
+ : base(SignatureSubpacketTag.KeyFlags, critical, isLongLength, data)
{
}
public KeyFlags(
- bool critical,
- int flags)
- : base(SignatureSubpacketTag.KeyFlags, critical, IntToByteArray(flags))
+ bool critical,
+ int flags)
+ : base(SignatureSubpacketTag.KeyFlags, critical, false, IntToByteArray(flags))
{
}
diff --git a/crypto/src/bcpg/sig/NotationData.cs b/crypto/src/bcpg/sig/NotationData.cs
index ccc9aa745..9ac6f89cf 100644
--- a/crypto/src/bcpg/sig/NotationData.cs
+++ b/crypto/src/bcpg/sig/NotationData.cs
@@ -17,8 +17,9 @@ namespace Org.BouncyCastle.Bcpg.Sig
public NotationData(
bool critical,
- byte[] data)
- : base(SignatureSubpacketTag.NotationData, critical, data)
+ bool isLongLength,
+ byte[] data)
+ : base(SignatureSubpacketTag.NotationData, critical, isLongLength, data)
{
}
@@ -27,12 +28,12 @@ namespace Org.BouncyCastle.Bcpg.Sig
bool humanReadable,
string notationName,
string notationValue)
- : base(SignatureSubpacketTag.NotationData, critical,
- createData(humanReadable, notationName, notationValue))
+ : base(SignatureSubpacketTag.NotationData, critical, false,
+ CreateData(humanReadable, notationName, notationValue))
{
}
- private static byte[] createData(
+ private static byte[] CreateData(
bool humanReadable,
string notationName,
string notationValue)
diff --git a/crypto/src/bcpg/sig/PreferredAlgorithms.cs b/crypto/src/bcpg/sig/PreferredAlgorithms.cs
index 0f282a38c..9514bed2b 100644
--- a/crypto/src/bcpg/sig/PreferredAlgorithms.cs
+++ b/crypto/src/bcpg/sig/PreferredAlgorithms.cs
@@ -1,7 +1,5 @@
using System;
-
-
namespace Org.BouncyCastle.Bcpg.Sig
{
/**
@@ -24,24 +22,25 @@ namespace Org.BouncyCastle.Bcpg.Sig
}
public PreferredAlgorithms(
- SignatureSubpacketTag type,
- bool critical,
- byte[] data)
- : base(type, critical, data)
+ SignatureSubpacketTag type,
+ bool critical,
+ bool isLongLength,
+ byte[] data)
+ : base(type, critical, isLongLength, data)
{
}
public PreferredAlgorithms(
- SignatureSubpacketTag type,
- bool critical,
- int[] preferences)
- : base(type, critical, IntToByteArray(preferences))
+ SignatureSubpacketTag type,
+ bool critical,
+ int[] preferences)
+ : base(type, critical, false, IntToByteArray(preferences))
{
}
public int[] GetPreferences()
{
- int[] v = new int[data.Length];
+ int[] v = new int[data.Length];
for (int i = 0; i != v.Length; i++)
{
diff --git a/crypto/src/bcpg/sig/PrimaryUserId.cs b/crypto/src/bcpg/sig/PrimaryUserId.cs
index fc0353afd..1f16f40eb 100644
--- a/crypto/src/bcpg/sig/PrimaryUserId.cs
+++ b/crypto/src/bcpg/sig/PrimaryUserId.cs
@@ -1,7 +1,5 @@
using System;
-
-
namespace Org.BouncyCastle.Bcpg.Sig
{
/**
@@ -28,15 +26,16 @@ namespace Org.BouncyCastle.Bcpg.Sig
public PrimaryUserId(
bool critical,
- byte[] data)
- : base(SignatureSubpacketTag.PrimaryUserId, critical, data)
+ bool isLongLength,
+ byte[] data)
+ : base(SignatureSubpacketTag.PrimaryUserId, critical, isLongLength, data)
{
}
public PrimaryUserId(
bool critical,
bool isPrimaryUserId)
- : base(SignatureSubpacketTag.PrimaryUserId, critical, BooleanToByteArray(isPrimaryUserId))
+ : base(SignatureSubpacketTag.PrimaryUserId, critical, false, BooleanToByteArray(isPrimaryUserId))
{
}
diff --git a/crypto/src/bcpg/sig/Revocable.cs b/crypto/src/bcpg/sig/Revocable.cs
index b5e94feec..7aa91391f 100644
--- a/crypto/src/bcpg/sig/Revocable.cs
+++ b/crypto/src/bcpg/sig/Revocable.cs
@@ -1,7 +1,5 @@
using System;
-
-
namespace Org.BouncyCastle.Bcpg.Sig
{
/**
@@ -28,16 +26,17 @@ namespace Org.BouncyCastle.Bcpg.Sig
public Revocable(
bool critical,
- byte[] data)
- : base(SignatureSubpacketTag.Revocable, critical, data)
- {
+ bool isLongLength,
+ byte[] data)
+ : base(SignatureSubpacketTag.Revocable, critical, isLongLength, data)
+ {
}
public Revocable(
bool critical,
bool isRevocable)
- : base(SignatureSubpacketTag.Revocable, critical, BooleanToByteArray(isRevocable))
- {
+ : base(SignatureSubpacketTag.Revocable, critical, false, BooleanToByteArray(isRevocable))
+ {
}
public bool IsRevocable()
diff --git a/crypto/src/bcpg/sig/RevocationKey.cs b/crypto/src/bcpg/sig/RevocationKey.cs
index 66982cb5a..11467d2af 100644
--- a/crypto/src/bcpg/sig/RevocationKey.cs
+++ b/crypto/src/bcpg/sig/RevocationKey.cs
@@ -14,17 +14,18 @@ namespace Org.BouncyCastle.Bcpg
// 20 octets of fingerprint
public RevocationKey(
bool isCritical,
- byte[] data)
- : base(SignatureSubpacketTag.RevocationKey, isCritical, data)
+ bool isLongLength,
+ byte[] data)
+ : base(SignatureSubpacketTag.RevocationKey, isCritical, isLongLength, data)
{
}
- public RevocationKey(
+ public RevocationKey(
bool isCritical,
RevocationKeyTag signatureClass,
PublicKeyAlgorithmTag keyAlgorithm,
byte[] fingerprint)
- : base(SignatureSubpacketTag.RevocationKey, isCritical,
+ : base(SignatureSubpacketTag.RevocationKey, isCritical, false,
CreateData(signatureClass, keyAlgorithm, fingerprint))
{
}
diff --git a/crypto/src/bcpg/sig/RevocationReason.cs b/crypto/src/bcpg/sig/RevocationReason.cs
index 98e9b0a3d..42afd5f5b 100644
--- a/crypto/src/bcpg/sig/RevocationReason.cs
+++ b/crypto/src/bcpg/sig/RevocationReason.cs
@@ -11,16 +11,16 @@ namespace Org.BouncyCastle.Bcpg
public class RevocationReason
: SignatureSubpacket
{
- public RevocationReason(bool isCritical, byte[] data)
- : base(SignatureSubpacketTag.RevocationReason, isCritical, data)
+ public RevocationReason(bool isCritical, bool isLongLength, byte[] data)
+ : base(SignatureSubpacketTag.RevocationReason, isCritical, isLongLength, data)
{
}
- public RevocationReason(
- bool isCritical,
- RevocationReasonTag reason,
- string description)
- : base(SignatureSubpacketTag.RevocationReason, isCritical, CreateData(reason, description))
+ public RevocationReason(
+ bool isCritical,
+ RevocationReasonTag reason,
+ string description)
+ : base(SignatureSubpacketTag.RevocationReason, isCritical, false, CreateData(reason, description))
{
}
diff --git a/crypto/src/bcpg/sig/SignatureCreationTime.cs b/crypto/src/bcpg/sig/SignatureCreationTime.cs
index e6f241f11..d172e5d52 100644
--- a/crypto/src/bcpg/sig/SignatureCreationTime.cs
+++ b/crypto/src/bcpg/sig/SignatureCreationTime.cs
@@ -21,18 +21,22 @@ namespace Org.BouncyCastle.Bcpg.Sig
data[3] = (byte)t;
return data;
}
+
public SignatureCreationTime(
- bool critical,
- byte[] data)
- : base(SignatureSubpacketTag.CreationTime, critical, data)
+ bool critical,
+ bool isLongLength,
+ byte[] data)
+ : base(SignatureSubpacketTag.CreationTime, critical, isLongLength, data)
{
}
+
public SignatureCreationTime(
- bool critical,
- DateTime date)
- : base(SignatureSubpacketTag.CreationTime, critical, TimeToBytes(date))
+ bool critical,
+ DateTime date)
+ : base(SignatureSubpacketTag.CreationTime, critical, false, TimeToBytes(date))
{
}
+
public DateTime GetTime()
{
long time = (long)(
diff --git a/crypto/src/bcpg/sig/SignatureExpirationTime.cs b/crypto/src/bcpg/sig/SignatureExpirationTime.cs
index 7fddf5743..24f0a9f8a 100644
--- a/crypto/src/bcpg/sig/SignatureExpirationTime.cs
+++ b/crypto/src/bcpg/sig/SignatureExpirationTime.cs
@@ -1,7 +1,5 @@
using System;
-
-
namespace Org.BouncyCastle.Bcpg.Sig
{
/**
@@ -11,29 +9,28 @@ namespace Org.BouncyCastle.Bcpg.Sig
: SignatureSubpacket
{
protected static byte[] TimeToBytes(
- long t)
+ long t)
{
- byte[] data = new byte[4];
-
+ byte[] data = new byte[4];
data[0] = (byte)(t >> 24);
data[1] = (byte)(t >> 16);
data[2] = (byte)(t >> 8);
data[3] = (byte)t;
-
return data;
}
public SignatureExpirationTime(
bool critical,
- byte[] data)
- : base(SignatureSubpacketTag.ExpireTime, critical, data)
- {
+ bool isLongLength,
+ byte[] data)
+ : base(SignatureSubpacketTag.ExpireTime, critical, isLongLength, data)
+ {
}
public SignatureExpirationTime(
bool critical,
- long seconds)
- : base(SignatureSubpacketTag.ExpireTime, critical, TimeToBytes(seconds))
+ long seconds)
+ : base(SignatureSubpacketTag.ExpireTime, critical, false, TimeToBytes(seconds))
{
}
diff --git a/crypto/src/bcpg/sig/SignerUserId.cs b/crypto/src/bcpg/sig/SignerUserId.cs
index 98cc808e7..8ab62ed2e 100644
--- a/crypto/src/bcpg/sig/SignerUserId.cs
+++ b/crypto/src/bcpg/sig/SignerUserId.cs
@@ -24,20 +24,21 @@ namespace Org.BouncyCastle.Bcpg.Sig
}
public SignerUserId(
- bool critical,
- byte[] data)
- : base(SignatureSubpacketTag.SignerUserId, critical, data)
+ bool critical,
+ bool isLongLength,
+ byte[] data)
+ : base(SignatureSubpacketTag.SignerUserId, critical, isLongLength, data)
{
}
- public SignerUserId(
- bool critical,
- string userId)
- : base(SignatureSubpacketTag.SignerUserId, critical, UserIdToBytes(userId))
+ public SignerUserId(
+ bool critical,
+ string userId)
+ : base(SignatureSubpacketTag.SignerUserId, critical, false, UserIdToBytes(userId))
{
}
- public string GetId()
+ public string GetId()
{
char[] chars = new char[data.Length];
diff --git a/crypto/src/bcpg/sig/TrustSignature.cs b/crypto/src/bcpg/sig/TrustSignature.cs
index bbadd3067..91458826d 100644
--- a/crypto/src/bcpg/sig/TrustSignature.cs
+++ b/crypto/src/bcpg/sig/TrustSignature.cs
@@ -16,17 +16,18 @@ namespace Org.BouncyCastle.Bcpg.Sig
}
public TrustSignature(
- bool critical,
- byte[] data)
- : base(SignatureSubpacketTag.TrustSig, critical, data)
+ bool critical,
+ bool isLongLength,
+ byte[] data)
+ : base(SignatureSubpacketTag.TrustSig, critical, isLongLength, data)
{
}
public TrustSignature(
- bool critical,
- int depth,
- int trustAmount)
- : base(SignatureSubpacketTag.TrustSig, critical, IntToByteArray(depth, trustAmount))
+ bool critical,
+ int depth,
+ int trustAmount)
+ : base(SignatureSubpacketTag.TrustSig, critical, false, IntToByteArray(depth, trustAmount))
{
}
diff --git a/crypto/src/cms/CMSSignedDataGenerator.cs b/crypto/src/cms/CMSSignedDataGenerator.cs
index 114b9631d..201cfc5c4 100644
--- a/crypto/src/cms/CMSSignedDataGenerator.cs
+++ b/crypto/src/cms/CMSSignedDataGenerator.cs
@@ -6,11 +6,11 @@ using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Cms;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
-using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.X509;
+using Org.BouncyCastle.Crypto.Operators;
namespace Org.BouncyCastle.Cms
{
@@ -43,7 +43,7 @@ namespace Org.BouncyCastle.Cms
{
private readonly CmsSignedGenerator outer;
- private readonly AsymmetricKeyParameter key;
+ private readonly ISignatureCalculator sigCalc;
private readonly SignerIdentifier signerIdentifier;
private readonly string digestOID;
private readonly string encOID;
@@ -61,8 +61,12 @@ namespace Org.BouncyCastle.Cms
CmsAttributeTableGenerator unsAttr,
Asn1.Cms.AttributeTable baseSignedTable)
{
+ string digestName = Helper.GetDigestAlgName(digestOID);
+
+ string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(encOID);
+
this.outer = outer;
- this.key = key;
+ this.sigCalc = new Asn1SignatureCalculator(signatureName, key);
this.signerIdentifier = signerIdentifier;
this.digestOID = digestOID;
this.encOID = encOID;
@@ -71,7 +75,25 @@ namespace Org.BouncyCastle.Cms
this.baseSignedTable = baseSignedTable;
}
- internal AlgorithmIdentifier DigestAlgorithmID
+ internal SignerInf(
+ CmsSignedGenerator outer,
+ ISignatureCalculator sigCalc,
+ SignerIdentifier signerIdentifier,
+ CmsAttributeTableGenerator sAttr,
+ CmsAttributeTableGenerator unsAttr,
+ Asn1.Cms.AttributeTable baseSignedTable)
+ {
+ this.outer = outer;
+ this.sigCalc = sigCalc;
+ this.signerIdentifier = signerIdentifier;
+ this.digestOID = new DefaultDigestAlgorithmIdentifierFinder().find((AlgorithmIdentifier)sigCalc.AlgorithmDetails).Algorithm.Id;
+ this.encOID = ((AlgorithmIdentifier)sigCalc.AlgorithmDetails).Algorithm.Id;
+ this.sAttr = sAttr;
+ this.unsAttr = unsAttr;
+ this.baseSignedTable = baseSignedTable;
+ }
+
+ internal AlgorithmIdentifier DigestAlgorithmID
{
get { return new AlgorithmIdentifier(new DerObjectIdentifier(digestOID), DerNull.Instance); }
}
@@ -95,8 +117,7 @@ namespace Org.BouncyCastle.Cms
string digestName = Helper.GetDigestAlgName(digestOID);
string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(encOID);
- ISigner sig = Helper.GetSignatureInstance(signatureName);
-
+
byte[] hash;
if (outer._digests.Contains(digestOID))
{
@@ -113,11 +134,12 @@ namespace Org.BouncyCastle.Cms
outer._digests.Add(digestOID, hash.Clone());
}
- sig.Init(true, new ParametersWithRandom(key, random));
+ IStreamCalculator calculator = sigCalc.CreateCalculator();
+
#if NETCF_1_0 || NETCF_2_0 || SILVERLIGHT
- Stream sigStr = new SigOutputStream(sig);
+ Stream sigStr = new SigOutputStream(calculator.Stream);
#else
- Stream sigStr = new BufferedStream(new SigOutputStream(sig));
+ Stream sigStr = new BufferedStream(calculator.Stream);
#endif
Asn1Set signedAttr = null;
@@ -152,7 +174,7 @@ namespace Org.BouncyCastle.Cms
}
sigStr.Close();
- byte[] sigBytes = sig.GenerateSignature();
+ byte[] sigBytes = ((IBlockResult)calculator.GetResult()).DoFinal();
Asn1Set unsignedAttr = null;
if (unsAttr != null)
@@ -170,7 +192,7 @@ namespace Org.BouncyCastle.Cms
// TODO[RSAPSS] Need the ability to specify non-default parameters
Asn1Encodable sigX509Parameters = SignerUtilities.GetDefaultX509Parameters(signatureName);
- AlgorithmIdentifier encAlgId = CmsSignedGenerator.GetEncAlgorithmIdentifier(
+ AlgorithmIdentifier encAlgId = Helper.GetEncAlgorithmIdentifier(
new DerObjectIdentifier(encOID), sigX509Parameters);
return new SignerInfo(signerIdentifier, digAlgId,
@@ -203,7 +225,7 @@ namespace Org.BouncyCastle.Cms
X509Certificate cert,
string digestOID)
{
- AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID);
+ AddSigner(privateKey, cert, Helper.GetEncOid(privateKey, digestOID), digestOID);
}
/**
@@ -234,7 +256,7 @@ namespace Org.BouncyCastle.Cms
byte[] subjectKeyID,
string digestOID)
{
- AddSigner(privateKey, subjectKeyID, GetEncOid(privateKey, digestOID), digestOID);
+ AddSigner(privateKey, subjectKeyID, Helper.GetEncOid(privateKey, digestOID), digestOID);
}
/**
@@ -267,7 +289,7 @@ namespace Org.BouncyCastle.Cms
Asn1.Cms.AttributeTable signedAttr,
Asn1.Cms.AttributeTable unsignedAttr)
{
- AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID,
+ AddSigner(privateKey, cert, Helper.GetEncOid(privateKey, digestOID), digestOID,
signedAttr, unsignedAttr);
}
@@ -311,7 +333,7 @@ namespace Org.BouncyCastle.Cms
Asn1.Cms.AttributeTable signedAttr,
Asn1.Cms.AttributeTable unsignedAttr)
{
- AddSigner(privateKey, subjectKeyID, GetEncOid(privateKey, digestOID), digestOID,
+ AddSigner(privateKey, subjectKeyID, Helper.GetEncOid(privateKey, digestOID), digestOID,
signedAttr, unsignedAttr);
}
@@ -349,7 +371,7 @@ namespace Org.BouncyCastle.Cms
CmsAttributeTableGenerator signedAttrGen,
CmsAttributeTableGenerator unsignedAttrGen)
{
- AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID,
+ AddSigner(privateKey, cert, Helper.GetEncOid(privateKey, digestOID), digestOID,
signedAttrGen, unsignedAttrGen);
}
@@ -378,7 +400,7 @@ namespace Org.BouncyCastle.Cms
CmsAttributeTableGenerator signedAttrGen,
CmsAttributeTableGenerator unsignedAttrGen)
{
- AddSigner(privateKey, subjectKeyID, GetEncOid(privateKey, digestOID), digestOID,
+ AddSigner(privateKey, subjectKeyID, Helper.GetEncOid(privateKey, digestOID), digestOID,
signedAttrGen, unsignedAttrGen);
}
@@ -397,7 +419,13 @@ namespace Org.BouncyCastle.Cms
signedAttrGen, unsignedAttrGen, null);
}
- private void doAddSigner(
+ public void AddSignerInfoGenerator(SignerInfoGenerator signerInfoGenerator)
+ {
+ signerInfs.Add(new SignerInf(this, signerInfoGenerator.contentSigner, signerInfoGenerator.sigId,
+ signerInfoGenerator.signedGen, signerInfoGenerator.unsignedGen, null));
+ }
+
+ private void doAddSigner(
AsymmetricKeyParameter privateKey,
SignerIdentifier signerIdentifier,
string encryptionOID,
diff --git a/crypto/src/cms/CMSSignedDataStreamGenerator.cs b/crypto/src/cms/CMSSignedDataStreamGenerator.cs
index 743e9c6c1..223fdb39d 100644
--- a/crypto/src/cms/CMSSignedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSSignedDataStreamGenerator.cs
@@ -52,10 +52,10 @@ namespace Org.BouncyCastle.Cms
private class DigestAndSignerInfoGeneratorHolder
{
- internal readonly SignerInfoGenerator signerInf;
+ internal readonly ISignerInfoGenerator signerInf;
internal readonly string digestOID;
- internal DigestAndSignerInfoGeneratorHolder(SignerInfoGenerator signerInf, String digestOID)
+ internal DigestAndSignerInfoGeneratorHolder(ISignerInfoGenerator signerInf, String digestOID)
{
this.signerInf = signerInf;
this.digestOID = digestOID;
@@ -67,7 +67,7 @@ namespace Org.BouncyCastle.Cms
}
}
- private class SignerInfoGeneratorImpl : SignerInfoGenerator
+ private class SignerInfoGeneratorImpl : ISignerInfoGenerator
{
private readonly CmsSignedDataStreamGenerator outer;
@@ -215,7 +215,7 @@ namespace Org.BouncyCastle.Cms
// TODO[RSAPSS] Need the ability to specify non-default parameters
Asn1Encodable sigX509Parameters = SignerUtilities.GetDefaultX509Parameters(signatureName);
- AlgorithmIdentifier digestEncryptionAlgorithm = CmsSignedGenerator.GetEncAlgorithmIdentifier(
+ AlgorithmIdentifier digestEncryptionAlgorithm = Helper.GetEncAlgorithmIdentifier(
new DerObjectIdentifier(_encOID), sigX509Parameters);
return new SignerInfo(_signerIdentifier, digestAlgorithm,
@@ -347,7 +347,7 @@ namespace Org.BouncyCastle.Cms
CmsAttributeTableGenerator signedAttrGenerator,
CmsAttributeTableGenerator unsignedAttrGenerator)
{
- AddSigner(privateKey, cert, GetEncOid(privateKey, digestOid), digestOid,
+ AddSigner(privateKey, cert, Helper.GetEncOid(privateKey, digestOid), digestOid,
signedAttrGenerator, unsignedAttrGenerator);
}
@@ -420,7 +420,7 @@ namespace Org.BouncyCastle.Cms
CmsAttributeTableGenerator signedAttrGenerator,
CmsAttributeTableGenerator unsignedAttrGenerator)
{
- AddSigner(privateKey, subjectKeyID, GetEncOid(privateKey, digestOid),
+ AddSigner(privateKey, subjectKeyID, Helper.GetEncOid(privateKey, digestOid),
digestOid, signedAttrGenerator, unsignedAttrGenerator);
}
diff --git a/crypto/src/cms/CMSSignedGenerator.cs b/crypto/src/cms/CMSSignedGenerator.cs
index f272c830e..0fb1f314d 100644
--- a/crypto/src/cms/CMSSignedGenerator.cs
+++ b/crypto/src/cms/CMSSignedGenerator.cs
@@ -16,12 +16,106 @@ using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Collections;
-using Org.BouncyCastle.Utilities.IO;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.X509.Store;
namespace Org.BouncyCastle.Cms
{
+ public class DefaultDigestAlgorithmIdentifierFinder
+ {
+ private static readonly IDictionary digestOids = Platform.CreateHashtable();
+ private static readonly IDictionary digestNameToOids = Platform.CreateHashtable();
+
+ static DefaultDigestAlgorithmIdentifierFinder()
+ {
+ //
+ // digests
+ //
+ digestOids.Add(OiwObjectIdentifiers.MD4WithRsaEncryption, PkcsObjectIdentifiers.MD4);
+ digestOids.Add(OiwObjectIdentifiers.MD4WithRsa, PkcsObjectIdentifiers.MD4);
+ digestOids.Add(OiwObjectIdentifiers.Sha1WithRsa, OiwObjectIdentifiers.IdSha1);
+
+ digestOids.Add(PkcsObjectIdentifiers.Sha224WithRsaEncryption, NistObjectIdentifiers.IdSha224);
+ digestOids.Add(PkcsObjectIdentifiers.Sha256WithRsaEncryption, NistObjectIdentifiers.IdSha256);
+ digestOids.Add(PkcsObjectIdentifiers.Sha384WithRsaEncryption, NistObjectIdentifiers.IdSha384);
+ digestOids.Add(PkcsObjectIdentifiers.Sha512WithRsaEncryption, NistObjectIdentifiers.IdSha512);
+ digestOids.Add(PkcsObjectIdentifiers.MD2WithRsaEncryption, PkcsObjectIdentifiers.MD2);
+ digestOids.Add(PkcsObjectIdentifiers.MD4WithRsaEncryption, PkcsObjectIdentifiers.MD4);
+ digestOids.Add(PkcsObjectIdentifiers.MD5WithRsaEncryption, PkcsObjectIdentifiers.MD5);
+ digestOids.Add(PkcsObjectIdentifiers.Sha1WithRsaEncryption, OiwObjectIdentifiers.IdSha1);
+
+ digestOids.Add(X9ObjectIdentifiers.ECDsaWithSha1, OiwObjectIdentifiers.IdSha1);
+ digestOids.Add(X9ObjectIdentifiers.ECDsaWithSha224, NistObjectIdentifiers.IdSha224);
+ digestOids.Add(X9ObjectIdentifiers.ECDsaWithSha256, NistObjectIdentifiers.IdSha256);
+ digestOids.Add(X9ObjectIdentifiers.ECDsaWithSha384, NistObjectIdentifiers.IdSha384);
+ digestOids.Add(X9ObjectIdentifiers.ECDsaWithSha512, NistObjectIdentifiers.IdSha512);
+ digestOids.Add(X9ObjectIdentifiers.IdDsaWithSha1, OiwObjectIdentifiers.IdSha1);
+
+ digestOids.Add(NistObjectIdentifiers.DsaWithSha224, NistObjectIdentifiers.IdSha224);
+ digestOids.Add(NistObjectIdentifiers.DsaWithSha256, NistObjectIdentifiers.IdSha256);
+ digestOids.Add(NistObjectIdentifiers.DsaWithSha384, NistObjectIdentifiers.IdSha384);
+ digestOids.Add(NistObjectIdentifiers.DsaWithSha512, NistObjectIdentifiers.IdSha512);
+
+ digestOids.Add(TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128, TeleTrusTObjectIdentifiers.RipeMD128);
+ digestOids.Add(TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160, TeleTrusTObjectIdentifiers.RipeMD160);
+ digestOids.Add(TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256, TeleTrusTObjectIdentifiers.RipeMD256);
+
+ digestOids.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94, CryptoProObjectIdentifiers.GostR3411);
+ digestOids.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001, CryptoProObjectIdentifiers.GostR3411);
+
+ digestNameToOids.Add("SHA-1", OiwObjectIdentifiers.IdSha1);
+ digestNameToOids.Add("SHA-224", NistObjectIdentifiers.IdSha224);
+ digestNameToOids.Add("SHA-256", NistObjectIdentifiers.IdSha256);
+ digestNameToOids.Add("SHA-384", NistObjectIdentifiers.IdSha384);
+ digestNameToOids.Add("SHA-512", NistObjectIdentifiers.IdSha512);
+
+ digestNameToOids.Add("SHA1", OiwObjectIdentifiers.IdSha1);
+ digestNameToOids.Add("SHA224", NistObjectIdentifiers.IdSha224);
+ digestNameToOids.Add("SHA256", NistObjectIdentifiers.IdSha256);
+ digestNameToOids.Add("SHA384", NistObjectIdentifiers.IdSha384);
+ digestNameToOids.Add("SHA512", NistObjectIdentifiers.IdSha512);
+
+ digestNameToOids.Add("SHA3-224", NistObjectIdentifiers.IdSha3_224);
+ digestNameToOids.Add("SHA3-256", NistObjectIdentifiers.IdSha3_256);
+ digestNameToOids.Add("SHA3-384", NistObjectIdentifiers.IdSha3_384);
+ digestNameToOids.Add("SHA3-512", NistObjectIdentifiers.IdSha3_512);
+
+ digestNameToOids.Add("SHAKE-128", NistObjectIdentifiers.IdShake128);
+ digestNameToOids.Add("SHAKE-256", NistObjectIdentifiers.IdShake256);
+
+ digestNameToOids.Add("GOST3411", CryptoProObjectIdentifiers.GostR3411);
+
+ digestNameToOids.Add("MD2", PkcsObjectIdentifiers.MD2);
+ digestNameToOids.Add("MD4", PkcsObjectIdentifiers.MD4);
+ digestNameToOids.Add("MD5", PkcsObjectIdentifiers.MD5);
+
+ digestNameToOids.Add("RIPEMD128", TeleTrusTObjectIdentifiers.RipeMD128);
+ digestNameToOids.Add("RIPEMD160", TeleTrusTObjectIdentifiers.RipeMD160);
+ digestNameToOids.Add("RIPEMD256", TeleTrusTObjectIdentifiers.RipeMD256);
+ }
+
+ public AlgorithmIdentifier find(AlgorithmIdentifier sigAlgId)
+ {
+ AlgorithmIdentifier digAlgId;
+
+ if (sigAlgId.Algorithm.Equals(PkcsObjectIdentifiers.IdRsassaPss))
+ {
+ digAlgId = RsassaPssParameters.GetInstance(sigAlgId.Parameters).HashAlgorithm;
+ }
+ else
+ {
+ digAlgId = new AlgorithmIdentifier((DerObjectIdentifier)digestOids[sigAlgId.Algorithm], DerNull.Instance);
+ }
+
+ return digAlgId;
+ }
+
+ public AlgorithmIdentifier find(String digAlgName)
+ {
+ return new AlgorithmIdentifier((DerObjectIdentifier)digestNameToOids[digAlgName], DerNull.Instance);
+ }
+ }
+
public class CmsSignedGenerator
{
/**
@@ -29,233 +123,145 @@ namespace Org.BouncyCastle.Cms
*/
public static readonly string Data = CmsObjectIdentifiers.Data.Id;
- public static readonly string DigestSha1 = OiwObjectIdentifiers.IdSha1.Id;
+ public static readonly string DigestSha1 = OiwObjectIdentifiers.IdSha1.Id;
public static readonly string DigestSha224 = NistObjectIdentifiers.IdSha224.Id;
public static readonly string DigestSha256 = NistObjectIdentifiers.IdSha256.Id;
public static readonly string DigestSha384 = NistObjectIdentifiers.IdSha384.Id;
public static readonly string DigestSha512 = NistObjectIdentifiers.IdSha512.Id;
public static readonly string DigestMD5 = PkcsObjectIdentifiers.MD5.Id;
public static readonly string DigestGost3411 = CryptoProObjectIdentifiers.GostR3411.Id;
- public static readonly string DigestRipeMD128 = TeleTrusTObjectIdentifiers.RipeMD128.Id;
- public static readonly string DigestRipeMD160 = TeleTrusTObjectIdentifiers.RipeMD160.Id;
- public static readonly string DigestRipeMD256 = TeleTrusTObjectIdentifiers.RipeMD256.Id;
+ public static readonly string DigestRipeMD128 = TeleTrusTObjectIdentifiers.RipeMD128.Id;
+ public static readonly string DigestRipeMD160 = TeleTrusTObjectIdentifiers.RipeMD160.Id;
+ public static readonly string DigestRipeMD256 = TeleTrusTObjectIdentifiers.RipeMD256.Id;
- public static readonly string EncryptionRsa = PkcsObjectIdentifiers.RsaEncryption.Id;
+ public static readonly string EncryptionRsa = PkcsObjectIdentifiers.RsaEncryption.Id;
public static readonly string EncryptionDsa = X9ObjectIdentifiers.IdDsaWithSha1.Id;
public static readonly string EncryptionECDsa = X9ObjectIdentifiers.ECDsaWithSha1.Id;
public static readonly string EncryptionRsaPss = PkcsObjectIdentifiers.IdRsassaPss.Id;
public static readonly string EncryptionGost3410 = CryptoProObjectIdentifiers.GostR3410x94.Id;
public static readonly string EncryptionECGost3410 = CryptoProObjectIdentifiers.GostR3410x2001.Id;
- private static readonly string EncryptionECDsaWithSha1 = X9ObjectIdentifiers.ECDsaWithSha1.Id;
- private static readonly string EncryptionECDsaWithSha224 = X9ObjectIdentifiers.ECDsaWithSha224.Id;
- private static readonly string EncryptionECDsaWithSha256 = X9ObjectIdentifiers.ECDsaWithSha256.Id;
- private static readonly string EncryptionECDsaWithSha384 = X9ObjectIdentifiers.ECDsaWithSha384.Id;
- private static readonly string EncryptionECDsaWithSha512 = X9ObjectIdentifiers.ECDsaWithSha512.Id;
-
- private static readonly ISet noParams = new HashSet();
- private static readonly IDictionary ecAlgorithms = Platform.CreateHashtable();
-
- static CmsSignedGenerator()
- {
- noParams.Add(EncryptionDsa);
-// noParams.Add(EncryptionECDsa);
- noParams.Add(EncryptionECDsaWithSha1);
- noParams.Add(EncryptionECDsaWithSha224);
- noParams.Add(EncryptionECDsaWithSha256);
- noParams.Add(EncryptionECDsaWithSha384);
- noParams.Add(EncryptionECDsaWithSha512);
-
- ecAlgorithms.Add(DigestSha1, EncryptionECDsaWithSha1);
- ecAlgorithms.Add(DigestSha224, EncryptionECDsaWithSha224);
- ecAlgorithms.Add(DigestSha256, EncryptionECDsaWithSha256);
- ecAlgorithms.Add(DigestSha384, EncryptionECDsaWithSha384);
- ecAlgorithms.Add(DigestSha512, EncryptionECDsaWithSha512);
- }
-
- internal IList _certs = Platform.CreateArrayList();
+ internal IList _certs = Platform.CreateArrayList();
internal IList _crls = Platform.CreateArrayList();
- internal IList _signers = Platform.CreateArrayList();
- internal IDictionary _digests = Platform.CreateHashtable();
-
- protected readonly SecureRandom rand;
-
- protected CmsSignedGenerator()
- : this(new SecureRandom())
- {
- }
-
- /// <summary>Constructor allowing specific source of randomness</summary>
- /// <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
- protected CmsSignedGenerator(
- SecureRandom rand)
- {
- this.rand = rand;
- }
-
- protected string GetEncOid(
- AsymmetricKeyParameter key,
- string digestOID)
+ internal IList _signers = Platform.CreateArrayList();
+ internal IDictionary _digests = Platform.CreateHashtable();
+
+ protected readonly SecureRandom rand;
+
+ protected CmsSignedGenerator()
+ : this(new SecureRandom())
{
- string encOID = null;
-
- if (key is RsaKeyParameters)
- {
- if (!((RsaKeyParameters) key).IsPrivate)
- throw new ArgumentException("Expected RSA private key");
-
- encOID = EncryptionRsa;
- }
- else if (key is DsaPrivateKeyParameters)
- {
- if (!digestOID.Equals(DigestSha1))
- throw new ArgumentException("can't mix DSA with anything but SHA1");
-
- encOID = EncryptionDsa;
- }
- else if (key is ECPrivateKeyParameters)
- {
- ECPrivateKeyParameters ecPrivKey = (ECPrivateKeyParameters) key;
- string algName = ecPrivKey.AlgorithmName;
-
- if (algName == "ECGOST3410")
- {
- encOID = EncryptionECGost3410;
- }
- else
- {
- // TODO Should we insist on algName being one of "EC" or "ECDSA", as Java does?
- encOID = (string) ecAlgorithms[digestOID];
-
- if (encOID == null)
- throw new ArgumentException("can't mix ECDSA with anything but SHA family digests");
- }
- }
- else if (key is Gost3410PrivateKeyParameters)
- {
- encOID = EncryptionGost3410;
- }
- else
- {
- throw new ArgumentException("Unknown algorithm in CmsSignedGenerator.GetEncOid");
- }
-
- return encOID;
}
- internal static AlgorithmIdentifier GetEncAlgorithmIdentifier(
- DerObjectIdentifier encOid,
- Asn1Encodable sigX509Parameters)
- {
- if (noParams.Contains(encOid.Id))
- {
- return new AlgorithmIdentifier(encOid);
- }
-
- return new AlgorithmIdentifier(encOid, sigX509Parameters);
- }
-
- internal protected virtual IDictionary GetBaseParameters(
- DerObjectIdentifier contentType,
- AlgorithmIdentifier digAlgId,
- byte[] hash)
- {
- IDictionary param = Platform.CreateHashtable();
+ /// <summary>Constructor allowing specific source of randomness</summary>
+ /// <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
+ protected CmsSignedGenerator(
+ SecureRandom rand)
+ {
+ this.rand = rand;
+ }
+
+ internal protected virtual IDictionary GetBaseParameters(
+ DerObjectIdentifier contentType,
+ AlgorithmIdentifier digAlgId,
+ byte[] hash)
+ {
+ IDictionary param = Platform.CreateHashtable();
if (contentType != null)
{
param[CmsAttributeTableParameter.ContentType] = contentType;
}
- param[CmsAttributeTableParameter.DigestAlgorithmIdentifier] = digAlgId;
+ param[CmsAttributeTableParameter.DigestAlgorithmIdentifier] = digAlgId;
param[CmsAttributeTableParameter.Digest] = hash.Clone();
return param;
- }
+ }
- internal protected virtual Asn1Set GetAttributeSet(
+ internal protected virtual Asn1Set GetAttributeSet(
Asn1.Cms.AttributeTable attr)
{
- return attr == null
- ? null
- : new DerSet(attr.ToAsn1EncodableVector());
+ return attr == null
+ ? null
+ : new DerSet(attr.ToAsn1EncodableVector());
}
- public void AddCertificates(
- IX509Store certStore)
- {
+ public void AddCertificates(
+ IX509Store certStore)
+ {
CollectionUtilities.AddRange(_certs, CmsUtilities.GetCertificatesFromStore(certStore));
}
- public void AddCrls(
- IX509Store crlStore)
- {
+ public void AddCrls(
+ IX509Store crlStore)
+ {
CollectionUtilities.AddRange(_crls, CmsUtilities.GetCrlsFromStore(crlStore));
- }
+ }
- /**
+ /**
* Add the attribute certificates contained in the passed in store to the
* generator.
*
* @param store a store of Version 2 attribute certificates
* @throws CmsException if an error occurse processing the store.
*/
- public void AddAttributeCertificates(
- IX509Store store)
- {
- try
- {
- foreach (IX509AttributeCertificate attrCert in store.GetMatches(null))
- {
- _certs.Add(new DerTaggedObject(false, 2,
- AttributeCertificate.GetInstance(Asn1Object.FromByteArray(attrCert.GetEncoded()))));
- }
- }
- catch (Exception e)
- {
- throw new CmsException("error processing attribute certs", e);
- }
- }
-
- /**
+ public void AddAttributeCertificates(
+ IX509Store store)
+ {
+ try
+ {
+ foreach (IX509AttributeCertificate attrCert in store.GetMatches(null))
+ {
+ _certs.Add(new DerTaggedObject(false, 2,
+ AttributeCertificate.GetInstance(Asn1Object.FromByteArray(attrCert.GetEncoded()))));
+ }
+ }
+ catch (Exception e)
+ {
+ throw new CmsException("error processing attribute certs", e);
+ }
+ }
+
+ /**
* Add a store of precalculated signers to the generator.
*
* @param signerStore store of signers
*/
- public void AddSigners(
- SignerInformationStore signerStore)
- {
- foreach (SignerInformation o in signerStore.GetSigners())
- {
- _signers.Add(o);
- AddSignerCallback(o);
- }
- }
-
- /**
+ public void AddSigners(
+ SignerInformationStore signerStore)
+ {
+ foreach (SignerInformation o in signerStore.GetSigners())
+ {
+ _signers.Add(o);
+ AddSignerCallback(o);
+ }
+ }
+
+ /**
* Return a map of oids and byte arrays representing the digests calculated on the content during
* the last generate.
*
* @return a map of oids (as String objects) and byte[] representing digests.
*/
- public IDictionary GetGeneratedDigests()
- {
- return Platform.CreateHashtable(_digests);
- }
-
- internal virtual void AddSignerCallback(
- SignerInformation si)
- {
- }
-
- internal static SignerIdentifier GetSignerIdentifier(X509Certificate cert)
- {
- return new SignerIdentifier(CmsUtilities.GetIssuerAndSerialNumber(cert));
- }
-
- internal static SignerIdentifier GetSignerIdentifier(byte[] subjectKeyIdentifier)
- {
- return new SignerIdentifier(new DerOctetString(subjectKeyIdentifier));
- }
- }
+ public IDictionary GetGeneratedDigests()
+ {
+ return Platform.CreateHashtable(_digests);
+ }
+
+ internal virtual void AddSignerCallback(
+ SignerInformation si)
+ {
+ }
+
+ internal static SignerIdentifier GetSignerIdentifier(X509Certificate cert)
+ {
+ return new SignerIdentifier(CmsUtilities.GetIssuerAndSerialNumber(cert));
+ }
+
+ internal static SignerIdentifier GetSignerIdentifier(byte[] subjectKeyIdentifier)
+ {
+ return new SignerIdentifier(new DerOctetString(subjectKeyIdentifier));
+ }
+ }
}
diff --git a/crypto/src/cms/CMSSignedHelper.cs b/crypto/src/cms/CMSSignedHelper.cs
index b3406fc06..23657ef86 100644
--- a/crypto/src/cms/CMSSignedHelper.cs
+++ b/crypto/src/cms/CMSSignedHelper.cs
@@ -18,6 +18,8 @@ using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.X509.Store;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Collections;
namespace Org.BouncyCastle.Cms
{
@@ -25,11 +27,20 @@ namespace Org.BouncyCastle.Cms
{
internal static readonly CmsSignedHelper Instance = new CmsSignedHelper();
- private static readonly IDictionary encryptionAlgs = Platform.CreateHashtable();
+ private static readonly string EncryptionECDsaWithSha1 = X9ObjectIdentifiers.ECDsaWithSha1.Id;
+ private static readonly string EncryptionECDsaWithSha224 = X9ObjectIdentifiers.ECDsaWithSha224.Id;
+ private static readonly string EncryptionECDsaWithSha256 = X9ObjectIdentifiers.ECDsaWithSha256.Id;
+ private static readonly string EncryptionECDsaWithSha384 = X9ObjectIdentifiers.ECDsaWithSha384.Id;
+ private static readonly string EncryptionECDsaWithSha512 = X9ObjectIdentifiers.ECDsaWithSha512.Id;
+
+ private static readonly IDictionary encryptionAlgs = Platform.CreateHashtable();
private static readonly IDictionary digestAlgs = Platform.CreateHashtable();
private static readonly IDictionary digestAliases = Platform.CreateHashtable();
- private static void AddEntries(DerObjectIdentifier oid, string digest, string encryption)
+ private static readonly ISet noParams = new HashSet();
+ private static readonly IDictionary ecAlgorithms = Platform.CreateHashtable();
+
+ private static void AddEntries(DerObjectIdentifier oid, string digest, string encryption)
{
string alias = oid.Id;
digestAlgs.Add(alias, digest);
@@ -100,7 +111,21 @@ namespace Org.BouncyCastle.Cms
digestAliases.Add("SHA256", new string[] { "SHA-256" });
digestAliases.Add("SHA384", new string[] { "SHA-384" });
digestAliases.Add("SHA512", new string[] { "SHA-512" });
- }
+
+ noParams.Add(CmsSignedGenerator.EncryptionDsa);
+ // noParams.Add(EncryptionECDsa);
+ noParams.Add(EncryptionECDsaWithSha1);
+ noParams.Add(EncryptionECDsaWithSha224);
+ noParams.Add(EncryptionECDsaWithSha256);
+ noParams.Add(EncryptionECDsaWithSha384);
+ noParams.Add(EncryptionECDsaWithSha512);
+
+ ecAlgorithms.Add(CmsSignedGenerator.DigestSha1, EncryptionECDsaWithSha1);
+ ecAlgorithms.Add(CmsSignedGenerator.DigestSha224, EncryptionECDsaWithSha224);
+ ecAlgorithms.Add(CmsSignedGenerator.DigestSha256, EncryptionECDsaWithSha256);
+ ecAlgorithms.Add(CmsSignedGenerator.DigestSha384, EncryptionECDsaWithSha384);
+ ecAlgorithms.Add(CmsSignedGenerator.DigestSha512, EncryptionECDsaWithSha512);
+ }
/**
* Return the digest algorithm using one of the standard JCA string
@@ -119,7 +144,19 @@ namespace Org.BouncyCastle.Cms
return digestAlgOid;
}
- internal string[] GetDigestAliases(
+ internal AlgorithmIdentifier GetEncAlgorithmIdentifier(
+ DerObjectIdentifier encOid,
+ Asn1Encodable sigX509Parameters)
+ {
+ if (noParams.Contains(encOid.Id))
+ {
+ return new AlgorithmIdentifier(encOid);
+ }
+
+ return new AlgorithmIdentifier(encOid, sigX509Parameters);
+ }
+
+ internal string[] GetDigestAliases(
string algName)
{
string[] aliases = (string[]) digestAliases[algName];
@@ -315,5 +352,75 @@ namespace Org.BouncyCastle.Cms
return algId;
}
+
+ internal string GetEncOid(
+ AsymmetricKeyParameter key,
+ string digestOID)
+ {
+ string encOID = null;
+
+ if (key is RsaKeyParameters)
+ {
+ if (!((RsaKeyParameters)key).IsPrivate)
+ throw new ArgumentException("Expected RSA private key");
+
+ encOID = CmsSignedGenerator.EncryptionRsa;
+ }
+ else if (key is DsaPrivateKeyParameters)
+ {
+ if (digestOID.Equals(CmsSignedGenerator.DigestSha1))
+ {
+ encOID = CmsSignedGenerator.EncryptionDsa;
+ }
+ else if (digestOID.Equals(CmsSignedGenerator.DigestSha224))
+ {
+ encOID = NistObjectIdentifiers.DsaWithSha224.Id;
+ }
+ else if (digestOID.Equals(CmsSignedGenerator.DigestSha256))
+ {
+ encOID = NistObjectIdentifiers.DsaWithSha256.Id;
+ }
+ else if (digestOID.Equals(CmsSignedGenerator.DigestSha384))
+ {
+ encOID = NistObjectIdentifiers.DsaWithSha384.Id;
+ }
+ else if (digestOID.Equals(CmsSignedGenerator.DigestSha512))
+ {
+ encOID = NistObjectIdentifiers.DsaWithSha512.Id;
+ }
+ else
+ {
+ throw new ArgumentException("can't mix DSA with anything but SHA1/SHA2");
+ }
+ }
+ else if (key is ECPrivateKeyParameters)
+ {
+ ECPrivateKeyParameters ecPrivKey = (ECPrivateKeyParameters)key;
+ string algName = ecPrivKey.AlgorithmName;
+
+ if (algName == "ECGOST3410")
+ {
+ encOID = CmsSignedGenerator.EncryptionECGost3410;
+ }
+ else
+ {
+ // TODO Should we insist on algName being one of "EC" or "ECDSA", as Java does?
+ encOID = (string)ecAlgorithms[digestOID];
+
+ if (encOID == null)
+ throw new ArgumentException("can't mix ECDSA with anything but SHA family digests");
+ }
+ }
+ else if (key is Gost3410PrivateKeyParameters)
+ {
+ encOID = CmsSignedGenerator.EncryptionGost3410;
+ }
+ else
+ {
+ throw new ArgumentException("Unknown algorithm in CmsSignedGenerator.GetEncOid");
+ }
+
+ return encOID;
+ }
}
}
diff --git a/crypto/src/cms/CMSTypedStream.cs b/crypto/src/cms/CMSTypedStream.cs
index 9cb314211..d04846ee1 100644
--- a/crypto/src/cms/CMSTypedStream.cs
+++ b/crypto/src/cms/CMSTypedStream.cs
@@ -2,7 +2,6 @@ using System;
using System.IO;
using Org.BouncyCastle.Asn1.Pkcs;
-using Org.BouncyCastle.Asn1.Utilities;
using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Cms
diff --git a/crypto/src/cms/SignerInfoGenerator.cs b/crypto/src/cms/SignerInfoGenerator.cs
index f78cf2c01..62db40ad8 100644
--- a/crypto/src/cms/SignerInfoGenerator.cs
+++ b/crypto/src/cms/SignerInfoGenerator.cs
@@ -3,12 +3,165 @@ using System;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Cms;
using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.X509;
namespace Org.BouncyCastle.Cms
{
- internal interface SignerInfoGenerator
- {
- SignerInfo Generate(DerObjectIdentifier contentType, AlgorithmIdentifier digestAlgorithm,
- byte[] calculatedDigest);
- }
+ internal interface ISignerInfoGenerator
+ {
+ SignerInfo Generate(DerObjectIdentifier contentType, AlgorithmIdentifier digestAlgorithm,
+ byte[] calculatedDigest);
+ }
+
+ public class SignerInfoGenerator
+ {
+ internal X509Certificate certificate;
+ internal ISignatureCalculator contentSigner;
+ internal SignerIdentifier sigId;
+ internal CmsAttributeTableGenerator signedGen;
+ internal CmsAttributeTableGenerator unsignedGen;
+ private bool isDirectSignature;
+
+ internal SignerInfoGenerator(SignerIdentifier sigId, ISignatureCalculator contentSigner): this(sigId, contentSigner, false)
+ {
+
+ }
+
+ internal SignerInfoGenerator(SignerIdentifier sigId, ISignatureCalculator contentSigner, bool isDirectSignature)
+ {
+ this.sigId = sigId;
+ this.contentSigner = contentSigner;
+ this.isDirectSignature = isDirectSignature;
+ if (this.isDirectSignature)
+ {
+ this.signedGen = null;
+ this.unsignedGen = null;
+ }
+ else
+ {
+ this.signedGen = new DefaultSignedAttributeTableGenerator();
+ this.unsignedGen = null;
+ }
+ }
+
+ internal SignerInfoGenerator(SignerIdentifier sigId, ISignatureCalculator contentSigner, CmsAttributeTableGenerator signedGen, CmsAttributeTableGenerator unsignedGen)
+ {
+ this.sigId = sigId;
+ this.contentSigner = contentSigner;
+ this.signedGen = signedGen;
+ this.unsignedGen = unsignedGen;
+ this.isDirectSignature = false;
+ }
+
+ internal void setAssociatedCertificate(X509Certificate certificate)
+ {
+ this.certificate = certificate;
+ }
+ }
+
+ public class SignerInfoGeneratorBuilder
+ {
+ private bool directSignature;
+ private CmsAttributeTableGenerator signedGen;
+ private CmsAttributeTableGenerator unsignedGen;
+
+ public SignerInfoGeneratorBuilder()
+ {
+ }
+
+ /**
+ * If the passed in flag is true, the signer signature will be based on the data, not
+ * a collection of signed attributes, and no signed attributes will be included.
+ *
+ * @return the builder object
+ */
+ public SignerInfoGeneratorBuilder SetDirectSignature(bool hasNoSignedAttributes)
+ {
+ this.directSignature = hasNoSignedAttributes;
+
+ return this;
+ }
+
+ /**
+ * Provide a custom signed attribute generator.
+ *
+ * @param signedGen a generator of signed attributes.
+ * @return the builder object
+ */
+ public SignerInfoGeneratorBuilder WithSignedAttributeGenerator(CmsAttributeTableGenerator signedGen)
+ {
+ this.signedGen = signedGen;
+
+ return this;
+ }
+
+ /**
+ * Provide a generator of unsigned attributes.
+ *
+ * @param unsignedGen a generator for signed attributes.
+ * @return the builder object
+ */
+ public SignerInfoGeneratorBuilder WithUnsignedAttributeGenerator(CmsAttributeTableGenerator unsignedGen)
+ {
+ this.unsignedGen = unsignedGen;
+
+ return this;
+ }
+
+ /**
+ * Build a generator with the passed in certHolder issuer and serial number as the signerIdentifier.
+ *
+ * @param contentSigner operator for generating the final signature in the SignerInfo with.
+ * @param certHolder carrier for the X.509 certificate related to the contentSigner.
+ * @return a SignerInfoGenerator
+ * @throws OperatorCreationException if the generator cannot be built.
+ */
+ public SignerInfoGenerator Build(ISignatureCalculator contentSigner, X509Certificate certificate)
+ {
+ SignerIdentifier sigId = new SignerIdentifier(new IssuerAndSerialNumber(certificate.IssuerDN, new DerInteger(certificate.SerialNumber)));
+
+ SignerInfoGenerator sigInfoGen = CreateGenerator(contentSigner, sigId);
+
+ sigInfoGen.setAssociatedCertificate(certificate);
+
+ return sigInfoGen;
+ }
+
+ /**
+ * Build a generator with the passed in subjectKeyIdentifier as the signerIdentifier. If used you should
+ * try to follow the calculation described in RFC 5280 section 4.2.1.2.
+ *
+ * @param contentSigner operator for generating the final signature in the SignerInfo with.
+ * @param subjectKeyIdentifier key identifier to identify the public key for verifying the signature.
+ * @return a SignerInfoGenerator
+ * @throws OperatorCreationException if the generator cannot be built.
+ */
+ public SignerInfoGenerator Build(ISignatureCalculator contentSigner, byte[] subjectKeyIdentifier)
+ {
+ SignerIdentifier sigId = new SignerIdentifier(new DerOctetString(subjectKeyIdentifier));
+
+ return CreateGenerator(contentSigner, sigId);
+ }
+
+ private SignerInfoGenerator CreateGenerator(ISignatureCalculator contentSigner, SignerIdentifier sigId)
+ {
+ if (directSignature)
+ {
+ return new SignerInfoGenerator(sigId, contentSigner, true);
+ }
+
+ if (signedGen != null || unsignedGen != null)
+ {
+ if (signedGen == null)
+ {
+ signedGen = new DefaultSignedAttributeTableGenerator();
+ }
+
+ return new SignerInfoGenerator(sigId, contentSigner, signedGen, unsignedGen);
+ }
+
+ return new SignerInfoGenerator(sigId, contentSigner);
+ }
+ }
}
diff --git a/crypto/src/crypto/IBlockResult.cs b/crypto/src/crypto/IBlockResult.cs
new file mode 100644
index 000000000..c12bdaa1d
--- /dev/null
+++ b/crypto/src/crypto/IBlockResult.cs
@@ -0,0 +1,24 @@
+
+namespace Org.BouncyCastle.Crypto
+{
+ /// <summary>
+ /// Operators that reduce their input to a single block return an object
+ /// of this type.
+ /// </summary>
+ public interface IBlockResult
+ {
+ /// <summary>
+ /// Return the final result of the operation.
+ /// </summary>
+ /// <returns>A block of bytes, representing the result of an operation.</returns>
+ byte[] DoFinal();
+
+ /// <summary>
+ /// Store the final result of the operation by copying it into the destination array.
+ /// </summary>
+ /// <returns>The number of bytes copied into destination.</returns>
+ /// <param name="destination">The byte array to copy the result into.</param>
+ /// <param name="offset">The offset into destination to start copying the result at.</param>
+ int DoFinal(byte[] destination, int offset);
+ }
+}
diff --git a/crypto/src/crypto/ISignatureCalculator.cs b/crypto/src/crypto/ISignatureCalculator.cs
new file mode 100644
index 000000000..bb733818d
--- /dev/null
+++ b/crypto/src/crypto/ISignatureCalculator.cs
@@ -0,0 +1,23 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto
+{
+ /// <summary>
+ /// Base interface for operators that serve as stream-based signature calculators.
+ /// </summary>
+ public interface ISignatureCalculator
+ {
+ /// <summary>The algorithm details object for this calculator.</summary>
+ Object AlgorithmDetails { get ; }
+
+ /// <summary>
+ /// Create a stream calculator for this signature calculator. The stream
+ /// calculator is used for the actual operation of entering the data to be signed
+ /// and producing the signature block.
+ /// </summary>
+ /// <returns>A calculator producing an IBlockResult with a signature in it.</returns>
+ IStreamCalculator CreateCalculator();
+ }
+}
+
+
diff --git a/crypto/src/crypto/ISignatureVerifier.cs b/crypto/src/crypto/ISignatureVerifier.cs
new file mode 100644
index 000000000..1f42a0256
--- /dev/null
+++ b/crypto/src/crypto/ISignatureVerifier.cs
@@ -0,0 +1,21 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto
+{
+ /// <summary>
+ /// Base interface for operators that serve as stream-based signature verifiers.
+ /// </summary>
+ public interface ISignatureVerifier
+ {
+ /// <summary>The algorithm details object for this verifier.</summary>
+ Object AlgorithmDetails { get ; }
+
+ /// <summary>
+ /// Create a stream calculator for this verifier. The stream
+ /// calculator is used for the actual operation of entering the data to be verified
+ /// and producing a result which can be used to verify the original signature.
+ /// </summary>
+ /// <returns>A calculator producing an IVerifier which can verify the signature.</returns>
+ IStreamCalculator CreateCalculator();
+ }
+}
diff --git a/crypto/src/crypto/ISignatureVerifierProvider.cs b/crypto/src/crypto/ISignatureVerifierProvider.cs
new file mode 100644
index 000000000..20180e22a
--- /dev/null
+++ b/crypto/src/crypto/ISignatureVerifierProvider.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto
+{
+ /// <summary>
+ /// Base interface for a provider to support the dynamic creation of signature verifiers.
+ /// </summary>
+ public interface ISignatureVerifierProvider
+ {
+ /// <summary>
+ /// Return a signature verfier for signature algorithm described in the passed in algorithm details object.
+ /// </summary>
+ /// <param name="algorithmDetails">The details of the signature algorithm verification is required for.</param>
+ /// <returns>A new signature verifier.</returns>
+ ISignatureVerifier CreateSignatureVerifier (Object algorithmDetails);
+ }
+}
+
diff --git a/crypto/src/crypto/IStreamCalculator.cs b/crypto/src/crypto/IStreamCalculator.cs
new file mode 100644
index 000000000..19a542845
--- /dev/null
+++ b/crypto/src/crypto/IStreamCalculator.cs
@@ -0,0 +1,23 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto
+{
+ /// <summary>
+ /// Base interface for cryptographic operations such as Hashes, MACs, and Signatures which reduce a stream of data
+ /// to a single value.
+ /// </summary>
+ public interface IStreamCalculator
+ {
+ /// <summary>Return a "sink" stream which only exists to update the implementing object.</summary>
+ /// <returns>A stream to write to in order to update the implementing object.</returns>
+ Stream Stream { get; }
+
+ /// <summary>
+ /// Return the result of processing the stream. This value is only available once the stream
+ /// has been closed.
+ /// </summary>
+ /// <returns>The result of processing the stream.</returns>
+ Object GetResult();
+ }
+}
diff --git a/crypto/src/crypto/IVerifier.cs b/crypto/src/crypto/IVerifier.cs
new file mode 100644
index 000000000..560cabf8e
--- /dev/null
+++ b/crypto/src/crypto/IVerifier.cs
@@ -0,0 +1,25 @@
+namespace Org.BouncyCastle.Crypto
+{
+ /// <summary>
+ /// Operators that reduce their input to the validation of a signature produce this type.
+ /// </summary>
+ public interface IVerifier
+ {
+ /// <summary>
+ /// Return true if the passed in data matches what is expected by the verification result.
+ /// </summary>
+ /// <param name="data">The bytes representing the signature.</param>
+ /// <returns>true if the signature verifies, false otherwise.</returns>
+ bool IsVerified(byte[] data);
+
+ /// <summary>
+ /// Return true if the length bytes from off in the source array match the signature
+ /// expected by the verification result.
+ /// </summary>
+ /// <param name="source">Byte array containing the signature.</param>
+ /// <param name="off">The offset into the source array where the signature starts.</param>
+ /// <param name="length">The number of bytes in source making up the signature.</param>
+ /// <returns>true if the signature verifies, false otherwise.</returns>
+ bool IsVerified(byte[] source, int off, int length);
+ }
+}
diff --git a/crypto/src/crypto/ec/CustomNamedCurves.cs b/crypto/src/crypto/ec/CustomNamedCurves.cs
index 0f13b4571..51bb1829a 100644
--- a/crypto/src/crypto/ec/CustomNamedCurves.cs
+++ b/crypto/src/crypto/ec/CustomNamedCurves.cs
@@ -60,7 +60,7 @@ namespace Org.BouncyCastle.Crypto.EC
*
* (The other possible y value is 5F51E65E475F794B1FE122D388B72EB36DC2B28192839E4DD6163A5D81312C14)
*/
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD245A"
+ "20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9"));
@@ -82,7 +82,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = Hex.Decode("000E0D4D696E6768756151750CC03A4473D03679");
ECCurve curve = ConfigureCurve(new SecP128R1Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "161FF7528B899B2D0C28607CA52C5B86"
+ "CF5AC8395BAFEB13C02DA292DDED7A83"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -115,7 +115,7 @@ namespace Org.BouncyCastle.Crypto.EC
new BigInteger("96341f1138933bc2f503fd44", 16),
176);
ECCurve curve = ConfigureCurveGlv(new SecP160K1Curve(), glv);
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB"
+ "938CF935318FDCED6BC28286531733C3F03C4FEE"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -136,7 +136,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = Hex.Decode("1053CDE42C14D696E67687561517533BF3F83345");
ECCurve curve = ConfigureCurve(new SecP160R1Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "4A96B5688EF573284664698968C38BB913CBFC82"
+ "23A628553168947D59DCC912042351377AC5FB32"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -157,7 +157,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = Hex.Decode("B99B99B099B323E02709A4D696E6768756151751");
ECCurve curve = ConfigureCurve(new SecP160R2Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "52DCB034293A117E1F4FF11B30F7199D3144CE6D"
+ "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -190,7 +190,7 @@ namespace Org.BouncyCastle.Crypto.EC
new BigInteger("b3fb3400dec5c4adceb8655d4c94", 16),
208);
ECCurve curve = ConfigureCurveGlv(new SecP192K1Curve(), glv);
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"
+ "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -211,7 +211,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = Hex.Decode("3045AE6FC8422F64ED579528D38120EAE12196D5");
ECCurve curve = ConfigureCurve(new SecP192R1Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"
+ "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -244,7 +244,7 @@ namespace Org.BouncyCastle.Crypto.EC
new BigInteger("b8adf1378a6eb73409fa6c9c637ba7f5", 16),
240);
ECCurve curve = ConfigureCurveGlv(new SecP224K1Curve(), glv);
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C"
+ "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -265,7 +265,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = Hex.Decode("BD71344799D5C7FCDC45B59FA3B9AB8F6A948BC5");
ECCurve curve = ConfigureCurve(new SecP224R1Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"
+ "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -298,7 +298,7 @@ namespace Org.BouncyCastle.Crypto.EC
new BigInteger("e4437ed6010e88286f547fa90abfe4c42212", 16),
272);
ECCurve curve = ConfigureCurveGlv(new SecP256K1Curve(), glv);
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
+ "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -319,7 +319,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = Hex.Decode("C49D360886E704936A6678E1139D26B7819F7E90");
ECCurve curve = ConfigureCurve(new SecP256R1Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"
+ "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -340,7 +340,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = Hex.Decode("A335926AA319A27A1D00896A6773A4827ACDAC73");
ECCurve curve = ConfigureCurve(new SecP384R1Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7"
+ "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -361,7 +361,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = Hex.Decode("D09E8800291CB85396CC6717393284AAA0DA64BA");
ECCurve curve = ConfigureCurve(new SecP521R1Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"
+ "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -382,7 +382,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = Hex.Decode("10E723AB14D696E6768756151756FEBF8FCB49A9");
ECCurve curve = ConfigureCurve(new SecT113R1Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "009D73616F35F4AB1407D73562C10F"
+ "00A52830277958EE84D1315ED31886"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -403,7 +403,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = Hex.Decode("10C0FB15760860DEF1EEF4D696E676875615175D");
ECCurve curve = ConfigureCurve(new SecT113R2Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "01A57A6A7B26CA5EF52FCDB8164797"
+ "00B3ADC94ED1FE674C06E695BABA1D"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -424,7 +424,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = Hex.Decode("4D696E676875615175985BD3ADBADA21B43A97E2");
ECCurve curve = ConfigureCurve(new SecT131R1Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "0081BAF91FDF9833C40F9C181343638399"
+ "078C6E7EA38C001F73C8134B1B4EF9E150"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -445,7 +445,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = Hex.Decode("985BD3ADBAD4D696E676875615175A21B43A97E3");
ECCurve curve = ConfigureCurve(new SecT131R2Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "0356DCD8F2F95031AD652D23951BB366A8"
+ "0648F06D867940A5366D9E265DE9EB240F"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -466,7 +466,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = null;
ECCurve curve = ConfigureCurve(new SecT163K1Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8"
+ "0289070FB05D38FF58321F2E800536D538CCDAA3D9"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -487,7 +487,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = Hex.Decode("24B7B137C8A14D696E6768756151756FD0DA2E5C");
ECCurve curve = ConfigureCurve(new SecT163R1Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "0369979697AB43897789566789567F787A7876A654"
+ "00435EDB42EFAFB2989D51FEFCE3C80988F41FF883"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -508,7 +508,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = Hex.Decode("85E25BFE5C86226CDB12016F7553F9D0E693A268");
ECCurve curve = ConfigureCurve(new SecT163R2Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "03F0EBA16286A2D57EA0991168D4994637E8343E36"
+ "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -529,7 +529,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = Hex.Decode("103FAEC74D696E676875615175777FC5B191EF30");
ECCurve curve = ConfigureCurve(new SecT193R1Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1"
+ "0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -550,7 +550,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = Hex.Decode("10B7B4D696E676875615175137C8A16FD0DA2211");
ECCurve curve = ConfigureCurve(new SecT193R2Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F"
+ "01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -571,7 +571,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = null;
ECCurve curve = ConfigureCurve(new SecT233K1Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126"
+ "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -592,7 +592,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = Hex.Decode("74D59FF07F6B413D0EA14B344B20A2DB049B50C3");
ECCurve curve = ConfigureCurve(new SecT233R1Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B"
+ "01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -613,7 +613,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = null;
ECCurve curve = ConfigureCurve(new SecT239K1Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC"
+ "76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -634,7 +634,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = null;
ECCurve curve = ConfigureCurve(new SecT283K1Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836"
+ "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -655,7 +655,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = Hex.Decode("77E2B07370EB0F832A6DD5B62DFC88CD06BB84BE");
ECCurve curve = ConfigureCurve(new SecT283R1Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053"
+ "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -676,7 +676,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = null;
ECCurve curve = ConfigureCurve(new SecT409K1Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746"
+ "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -697,7 +697,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = Hex.Decode("4099B5A457F9D69F79213D094C4BCD4D4262210B");
ECCurve curve = ConfigureCurve(new SecT409R1Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7"
+ "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -718,7 +718,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = null;
ECCurve curve = ConfigureCurve(new SecT571K1Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972"
+ "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
@@ -739,7 +739,7 @@ namespace Org.BouncyCastle.Crypto.EC
{
byte[] S = Hex.Decode("2AA058F73A0E33AB486B0F610410C53A7F132310");
ECCurve curve = ConfigureCurve(new SecT571R1Curve());
- ECPoint G = curve.DecodePoint(Hex.Decode("04"
+ X9ECPoint G = new X9ECPoint(curve, Hex.Decode("04"
+ "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19"
+ "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B"));
return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
diff --git a/crypto/src/crypto/engines/RSABlindedEngine.cs b/crypto/src/crypto/engines/RSABlindedEngine.cs
index 037abf7e9..f95f145f6 100644
--- a/crypto/src/crypto/engines/RSABlindedEngine.cs
+++ b/crypto/src/crypto/engines/RSABlindedEngine.cs
@@ -7,118 +7,122 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Engines
{
- /**
- * this does your basic RSA algorithm with blinding
- */
- public class RsaBlindedEngine
- : IAsymmetricBlockCipher
- {
- private readonly RsaCoreEngine core = new RsaCoreEngine();
- private RsaKeyParameters key;
- private SecureRandom random;
+ /**
+ * this does your basic RSA algorithm with blinding
+ */
+ public class RsaBlindedEngine
+ : IAsymmetricBlockCipher
+ {
+ private readonly RsaCoreEngine core = new RsaCoreEngine();
+ private RsaKeyParameters key;
+ private SecureRandom random;
public virtual string AlgorithmName
- {
- get { return "RSA"; }
- }
+ {
+ get { return "RSA"; }
+ }
- /**
- * initialise the RSA engine.
- *
- * @param forEncryption true if we are encrypting, false otherwise.
- * @param param the necessary RSA key parameters.
- */
+ /**
+ * initialise the RSA engine.
+ *
+ * @param forEncryption true if we are encrypting, false otherwise.
+ * @param param the necessary RSA key parameters.
+ */
public virtual void Init(
- bool forEncryption,
- ICipherParameters param)
- {
- core.Init(forEncryption, param);
+ bool forEncryption,
+ ICipherParameters param)
+ {
+ core.Init(forEncryption, param);
- if (param is ParametersWithRandom)
- {
- ParametersWithRandom rParam = (ParametersWithRandom)param;
+ if (param is ParametersWithRandom)
+ {
+ ParametersWithRandom rParam = (ParametersWithRandom)param;
- key = (RsaKeyParameters)rParam.Parameters;
- random = rParam.Random;
- }
- else
- {
- key = (RsaKeyParameters)param;
- random = new SecureRandom();
- }
- }
+ key = (RsaKeyParameters)rParam.Parameters;
+ random = rParam.Random;
+ }
+ else
+ {
+ key = (RsaKeyParameters)param;
+ random = new SecureRandom();
+ }
+ }
- /**
- * Return the maximum size for an input block to this engine.
- * For RSA this is always one byte less than the key size on
- * encryption, and the same length as the key size on decryption.
- *
- * @return maximum size for an input block.
- */
+ /**
+ * Return the maximum size for an input block to this engine.
+ * For RSA this is always one byte less than the key size on
+ * encryption, and the same length as the key size on decryption.
+ *
+ * @return maximum size for an input block.
+ */
public virtual int GetInputBlockSize()
- {
- return core.GetInputBlockSize();
- }
+ {
+ return core.GetInputBlockSize();
+ }
- /**
- * Return the maximum size for an output block to this engine.
- * For RSA this is always one byte less than the key size on
- * decryption, and the same length as the key size on encryption.
- *
- * @return maximum size for an output block.
- */
+ /**
+ * Return the maximum size for an output block to this engine.
+ * For RSA this is always one byte less than the key size on
+ * decryption, and the same length as the key size on encryption.
+ *
+ * @return maximum size for an output block.
+ */
public virtual int GetOutputBlockSize()
- {
- return core.GetOutputBlockSize();
- }
+ {
+ return core.GetOutputBlockSize();
+ }
- /**
- * Process a single block using the basic RSA algorithm.
- *
- * @param inBuf the input array.
- * @param inOff the offset into the input buffer where the data starts.
- * @param inLen the length of the data to be processed.
- * @return the result of the RSA process.
- * @exception DataLengthException the input block is too large.
- */
+ /**
+ * Process a single block using the basic RSA algorithm.
+ *
+ * @param inBuf the input array.
+ * @param inOff the offset into the input buffer where the data starts.
+ * @param inLen the length of the data to be processed.
+ * @return the result of the RSA process.
+ * @exception DataLengthException the input block is too large.
+ */
public virtual byte[] ProcessBlock(
- byte[] inBuf,
- int inOff,
- int inLen)
- {
- if (key == null)
- throw new InvalidOperationException("RSA engine not initialised");
+ byte[] inBuf,
+ int inOff,
+ int inLen)
+ {
+ if (key == null)
+ throw new InvalidOperationException("RSA engine not initialised");
- BigInteger input = core.ConvertInput(inBuf, inOff, inLen);
+ BigInteger input = core.ConvertInput(inBuf, inOff, inLen);
- BigInteger result;
- if (key is RsaPrivateCrtKeyParameters)
- {
- RsaPrivateCrtKeyParameters k = (RsaPrivateCrtKeyParameters)key;
- BigInteger e = k.PublicExponent;
- if (e != null) // can't do blinding without a public exponent
- {
- BigInteger m = k.Modulus;
- BigInteger r = BigIntegers.CreateRandomInRange(
- BigInteger.One, m.Subtract(BigInteger.One), random);
+ BigInteger result;
+ if (key is RsaPrivateCrtKeyParameters)
+ {
+ RsaPrivateCrtKeyParameters k = (RsaPrivateCrtKeyParameters)key;
+ BigInteger e = k.PublicExponent;
+ if (e != null) // can't do blinding without a public exponent
+ {
+ BigInteger m = k.Modulus;
+ BigInteger r = BigIntegers.CreateRandomInRange(
+ BigInteger.One, m.Subtract(BigInteger.One), random);
- BigInteger blindedInput = r.ModPow(e, m).Multiply(input).Mod(m);
- BigInteger blindedResult = core.ProcessBlock(blindedInput);
+ BigInteger blindedInput = r.ModPow(e, m).Multiply(input).Mod(m);
+ BigInteger blindedResult = core.ProcessBlock(blindedInput);
- BigInteger rInv = r.ModInverse(m);
- result = blindedResult.Multiply(rInv).Mod(m);
- }
- else
- {
- result = core.ProcessBlock(input);
- }
- }
- else
- {
- result = core.ProcessBlock(input);
- }
+ BigInteger rInv = r.ModInverse(m);
+ result = blindedResult.Multiply(rInv).Mod(m);
- return core.ConvertOutput(result);
- }
- }
+ // defence against Arjen Lenstra’s CRT attack
+ if (!input.Equals(result.ModPow(e, m)))
+ throw new InvalidOperationException("RSA engine faulty decryption/signing detected");
+ }
+ else
+ {
+ result = core.ProcessBlock(input);
+ }
+ }
+ else
+ {
+ result = core.ProcessBlock(input);
+ }
+
+ return core.ConvertOutput(result);
+ }
+ }
}
diff --git a/crypto/src/crypto/operators/Asn1Signature.cs b/crypto/src/crypto/operators/Asn1Signature.cs
new file mode 100644
index 000000000..ba070f4fc
--- /dev/null
+++ b/crypto/src/crypto/operators/Asn1Signature.cs
@@ -0,0 +1,559 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Crypto.Operators
+{
+ internal class X509Utilities
+ {
+ private static readonly Asn1Null derNull = DerNull.Instance;
+
+ private static readonly IDictionary algorithms = Platform.CreateHashtable();
+ private static readonly IDictionary exParams = Platform.CreateHashtable();
+ private static readonly ISet noParams = new HashSet();
+
+ static X509Utilities()
+ {
+ algorithms.Add("MD2WITHRSAENCRYPTION", PkcsObjectIdentifiers.MD2WithRsaEncryption);
+ algorithms.Add("MD2WITHRSA", PkcsObjectIdentifiers.MD2WithRsaEncryption);
+ algorithms.Add("MD5WITHRSAENCRYPTION", PkcsObjectIdentifiers.MD5WithRsaEncryption);
+ algorithms.Add("MD5WITHRSA", PkcsObjectIdentifiers.MD5WithRsaEncryption);
+ algorithms.Add("SHA1WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha1WithRsaEncryption);
+ algorithms.Add("SHA1WITHRSA", PkcsObjectIdentifiers.Sha1WithRsaEncryption);
+ algorithms.Add("SHA224WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha224WithRsaEncryption);
+ algorithms.Add("SHA224WITHRSA", PkcsObjectIdentifiers.Sha224WithRsaEncryption);
+ algorithms.Add("SHA256WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha256WithRsaEncryption);
+ algorithms.Add("SHA256WITHRSA", PkcsObjectIdentifiers.Sha256WithRsaEncryption);
+ algorithms.Add("SHA384WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha384WithRsaEncryption);
+ algorithms.Add("SHA384WITHRSA", PkcsObjectIdentifiers.Sha384WithRsaEncryption);
+ algorithms.Add("SHA512WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha512WithRsaEncryption);
+ algorithms.Add("SHA512WITHRSA", PkcsObjectIdentifiers.Sha512WithRsaEncryption);
+ algorithms.Add("SHA1WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
+ algorithms.Add("SHA224WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
+ algorithms.Add("SHA256WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
+ algorithms.Add("SHA384WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
+ algorithms.Add("SHA512WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
+ algorithms.Add("RIPEMD160WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160);
+ algorithms.Add("RIPEMD160WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160);
+ algorithms.Add("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128);
+ algorithms.Add("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128);
+ algorithms.Add("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256);
+ algorithms.Add("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256);
+ algorithms.Add("SHA1WITHDSA", X9ObjectIdentifiers.IdDsaWithSha1);
+ algorithms.Add("DSAWITHSHA1", X9ObjectIdentifiers.IdDsaWithSha1);
+ algorithms.Add("SHA224WITHDSA", NistObjectIdentifiers.DsaWithSha224);
+ algorithms.Add("SHA256WITHDSA", NistObjectIdentifiers.DsaWithSha256);
+ algorithms.Add("SHA384WITHDSA", NistObjectIdentifiers.DsaWithSha384);
+ algorithms.Add("SHA512WITHDSA", NistObjectIdentifiers.DsaWithSha512);
+ algorithms.Add("SHA1WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha1);
+ algorithms.Add("ECDSAWITHSHA1", X9ObjectIdentifiers.ECDsaWithSha1);
+ algorithms.Add("SHA224WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha224);
+ algorithms.Add("SHA256WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha256);
+ algorithms.Add("SHA384WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha384);
+ algorithms.Add("SHA512WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha512);
+ algorithms.Add("GOST3411WITHGOST3410", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
+ algorithms.Add("GOST3411WITHGOST3410-94", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
+ algorithms.Add("GOST3411WITHECGOST3410", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
+ algorithms.Add("GOST3411WITHECGOST3410-2001", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
+ algorithms.Add("GOST3411WITHGOST3410-2001", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
+
+ //
+ // According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field.
+ // The parameters field SHALL be NULL for RSA based signature algorithms.
+ //
+ noParams.Add(X9ObjectIdentifiers.ECDsaWithSha1);
+ noParams.Add(X9ObjectIdentifiers.ECDsaWithSha224);
+ noParams.Add(X9ObjectIdentifiers.ECDsaWithSha256);
+ noParams.Add(X9ObjectIdentifiers.ECDsaWithSha384);
+ noParams.Add(X9ObjectIdentifiers.ECDsaWithSha512);
+ noParams.Add(X9ObjectIdentifiers.IdDsaWithSha1);
+ noParams.Add(NistObjectIdentifiers.DsaWithSha224);
+ noParams.Add(NistObjectIdentifiers.DsaWithSha256);
+ noParams.Add(NistObjectIdentifiers.DsaWithSha384);
+ noParams.Add(NistObjectIdentifiers.DsaWithSha512);
+
+ //
+ // RFC 4491
+ //
+ noParams.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
+ noParams.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
+
+ //
+ // explicit params
+ //
+ AlgorithmIdentifier sha1AlgId = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance);
+ exParams.Add("SHA1WITHRSAANDMGF1", CreatePssParams(sha1AlgId, 20));
+
+ AlgorithmIdentifier sha224AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha224, DerNull.Instance);
+ exParams.Add("SHA224WITHRSAANDMGF1", CreatePssParams(sha224AlgId, 28));
+
+ AlgorithmIdentifier sha256AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha256, DerNull.Instance);
+ exParams.Add("SHA256WITHRSAANDMGF1", CreatePssParams(sha256AlgId, 32));
+
+ AlgorithmIdentifier sha384AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha384, DerNull.Instance);
+ exParams.Add("SHA384WITHRSAANDMGF1", CreatePssParams(sha384AlgId, 48));
+
+ AlgorithmIdentifier sha512AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha512, DerNull.Instance);
+ exParams.Add("SHA512WITHRSAANDMGF1", CreatePssParams(sha512AlgId, 64));
+ }
+
+ /**
+ * Return the digest algorithm using one of the standard JCA string
+ * representations rather than the algorithm identifier (if possible).
+ */
+ private static string GetDigestAlgName(
+ DerObjectIdentifier digestAlgOID)
+ {
+ if (PkcsObjectIdentifiers.MD5.Equals(digestAlgOID))
+ {
+ return "MD5";
+ }
+ else if (OiwObjectIdentifiers.IdSha1.Equals(digestAlgOID))
+ {
+ return "SHA1";
+ }
+ else if (NistObjectIdentifiers.IdSha224.Equals(digestAlgOID))
+ {
+ return "SHA224";
+ }
+ else if (NistObjectIdentifiers.IdSha256.Equals(digestAlgOID))
+ {
+ return "SHA256";
+ }
+ else if (NistObjectIdentifiers.IdSha384.Equals(digestAlgOID))
+ {
+ return "SHA384";
+ }
+ else if (NistObjectIdentifiers.IdSha512.Equals(digestAlgOID))
+ {
+ return "SHA512";
+ }
+ else if (TeleTrusTObjectIdentifiers.RipeMD128.Equals(digestAlgOID))
+ {
+ return "RIPEMD128";
+ }
+ else if (TeleTrusTObjectIdentifiers.RipeMD160.Equals(digestAlgOID))
+ {
+ return "RIPEMD160";
+ }
+ else if (TeleTrusTObjectIdentifiers.RipeMD256.Equals(digestAlgOID))
+ {
+ return "RIPEMD256";
+ }
+ else if (CryptoProObjectIdentifiers.GostR3411.Equals(digestAlgOID))
+ {
+ return "GOST3411";
+ }
+ else
+ {
+ return digestAlgOID.Id;
+ }
+ }
+
+ internal static string GetSignatureName(AlgorithmIdentifier sigAlgId)
+ {
+ Asn1Encodable parameters = sigAlgId.Parameters;
+
+ if (parameters != null && !derNull.Equals(parameters))
+ {
+ if (sigAlgId.ObjectID.Equals(PkcsObjectIdentifiers.IdRsassaPss))
+ {
+ RsassaPssParameters rsaParams = RsassaPssParameters.GetInstance(parameters);
+
+ return GetDigestAlgName(rsaParams.HashAlgorithm.ObjectID) + "withRSAandMGF1";
+ }
+ if (sigAlgId.ObjectID.Equals(X9ObjectIdentifiers.ECDsaWithSha2))
+ {
+ Asn1Sequence ecDsaParams = Asn1Sequence.GetInstance(parameters);
+
+ return GetDigestAlgName((DerObjectIdentifier)ecDsaParams[0]) + "withECDSA";
+ }
+ }
+
+ return sigAlgId.ObjectID.Id;
+ }
+
+ private static RsassaPssParameters CreatePssParams(
+ AlgorithmIdentifier hashAlgId,
+ int saltSize)
+ {
+ return new RsassaPssParameters(
+ hashAlgId,
+ new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, hashAlgId),
+ new DerInteger(saltSize),
+ new DerInteger(1));
+ }
+
+ internal static DerObjectIdentifier GetAlgorithmOid(
+ string algorithmName)
+ {
+ algorithmName = Platform.ToUpperInvariant(algorithmName);
+
+ if (algorithms.Contains(algorithmName))
+ {
+ return (DerObjectIdentifier) algorithms[algorithmName];
+ }
+
+ return new DerObjectIdentifier(algorithmName);
+ }
+
+ internal static AlgorithmIdentifier GetSigAlgID(
+ DerObjectIdentifier sigOid,
+ string algorithmName)
+ {
+ if (noParams.Contains(sigOid))
+ {
+ return new AlgorithmIdentifier(sigOid);
+ }
+
+ algorithmName = Platform.ToUpperInvariant(algorithmName);
+
+ if (exParams.Contains(algorithmName))
+ {
+ return new AlgorithmIdentifier(sigOid, (Asn1Encodable) exParams[algorithmName]);
+ }
+
+ return new AlgorithmIdentifier(sigOid, DerNull.Instance);
+ }
+
+ internal static IEnumerable GetAlgNames()
+ {
+ return new EnumerableProxy(algorithms.Keys);
+ }
+ }
+
+ internal class SignerBucket
+ : Stream
+ {
+ protected readonly ISigner signer;
+
+ public SignerBucket(
+ ISigner signer)
+ {
+ this.signer = signer;
+ }
+
+ public override int Read(
+ byte[] buffer,
+ int offset,
+ int count)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override int ReadByte()
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override void Write(
+ byte[] buffer,
+ int offset,
+ int count)
+ {
+ if (count > 0)
+ {
+ signer.BlockUpdate(buffer, offset, count);
+ }
+ }
+
+ public override void WriteByte(
+ byte b)
+ {
+ signer.Update(b);
+ }
+
+ public override bool CanRead
+ {
+ get { return false; }
+ }
+
+ public override bool CanWrite
+ {
+ get { return true; }
+ }
+
+ public override bool CanSeek
+ {
+ get { return false; }
+ }
+
+ public override long Length
+ {
+ get { return 0; }
+ }
+
+ public override long Position
+ {
+ get { throw new NotImplementedException (); }
+ set { throw new NotImplementedException (); }
+ }
+
+ public override void Close()
+ {
+ }
+
+ public override void Flush()
+ {
+ }
+
+ public override long Seek(
+ long offset,
+ SeekOrigin origin)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override void SetLength(
+ long length)
+ {
+ throw new NotImplementedException ();
+ }
+ }
+
+ /// <summary>
+ /// Calculator class for signature generation in ASN.1 based profiles that use an AlgorithmIdentifier to preserve
+ /// signature algorithm details.
+ /// </summary>
+ public class Asn1SignatureCalculator: ISignatureCalculator
+ {
+ private readonly AlgorithmIdentifier algID;
+ private readonly string algorithm;
+ private readonly AsymmetricKeyParameter privateKey;
+ private readonly SecureRandom random;
+
+ /// <summary>
+ /// Base constructor.
+ /// </summary>
+ /// <param name="algorithm">The name of the signature algorithm to use.</param>
+ /// <param name="privateKey">The private key to be used in the signing operation.</param>
+ public Asn1SignatureCalculator (string algorithm, AsymmetricKeyParameter privateKey): this(algorithm, privateKey, null)
+ {
+ }
+
+ /// <summary>
+ /// Constructor which also specifies a source of randomness to be used if one is required.
+ /// </summary>
+ /// <param name="algorithm">The name of the signature algorithm to use.</param>
+ /// <param name="privateKey">The private key to be used in the signing operation.</param>
+ /// <param name="random">The source of randomness to be used in signature calculation.</param>
+ public Asn1SignatureCalculator (string algorithm, AsymmetricKeyParameter privateKey, SecureRandom random)
+ {
+ DerObjectIdentifier sigOid = X509Utilities.GetAlgorithmOid (algorithm);
+
+ this.algorithm = algorithm;
+ this.privateKey = privateKey;
+ this.random = random;
+ this.algID = X509Utilities.GetSigAlgID (sigOid, algorithm);
+ }
+
+ public Object AlgorithmDetails
+ {
+ get { return this.algID; }
+ }
+
+ public IStreamCalculator CreateCalculator()
+ {
+ ISigner sig = SignerUtilities.GetSigner(algorithm);
+
+ if (random != null)
+ {
+ sig.Init(true, new ParametersWithRandom(privateKey, random));
+ }
+ else
+ {
+ sig.Init(true, privateKey);
+ }
+
+ return new SigCalculator(sig);
+ }
+
+ /// <summary>
+ /// Allows enumeration of the signature names supported by the verifier provider.
+ /// </summary>
+ public static IEnumerable SignatureAlgNames
+ {
+ get { return X509Utilities.GetAlgNames(); }
+ }
+ }
+
+ internal class SigCalculator : IStreamCalculator
+ {
+ private readonly ISigner sig;
+ private readonly Stream stream;
+
+ internal SigCalculator(ISigner sig)
+ {
+ this.sig = sig;
+ this.stream = new SignerBucket(sig);
+ }
+
+ public Stream Stream
+ {
+ get { return stream; }
+ }
+
+ public object GetResult()
+ {
+ return new SigResult(sig);
+ }
+ }
+
+ internal class SigResult : IBlockResult
+ {
+ private readonly ISigner sig;
+
+ internal SigResult(ISigner sig)
+ {
+ this.sig = sig;
+ }
+
+ public byte[] DoFinal()
+ {
+ return sig.GenerateSignature();
+ }
+
+ public int DoFinal(byte[] destination, int offset)
+ {
+ byte[] signature = DoFinal();
+
+ Array.Copy(signature, 0, destination, offset, signature.Length);
+
+ return signature.Length;
+ }
+ }
+
+ /// <summary>
+ /// Verifier class for signature verification in ASN.1 based profiles that use an AlgorithmIdentifier to preserve
+ /// signature algorithm details.
+ /// </summary>
+ public class Asn1SignatureVerifier: ISignatureVerifier
+ {
+ private readonly AlgorithmIdentifier algID;
+ private readonly AsymmetricKeyParameter publicKey;
+
+ /// <summary>
+ /// Base constructor.
+ /// </summary>
+ /// <param name="algorithm">The name of the signature algorithm to use.</param>
+ /// <param name="publicKey">The public key to be used in the verification operation.</param>
+ public Asn1SignatureVerifier (String algorithm, AsymmetricKeyParameter publicKey)
+ {
+ DerObjectIdentifier sigOid = X509Utilities.GetAlgorithmOid (algorithm);
+
+ this.publicKey = publicKey;
+ this.algID = X509Utilities.GetSigAlgID (sigOid, algorithm);
+ }
+
+ public Asn1SignatureVerifier (AlgorithmIdentifier algorithm, AsymmetricKeyParameter publicKey)
+ {
+ this.publicKey = publicKey;
+ this.algID = algorithm;
+ }
+
+ public Object AlgorithmDetails
+ {
+ get { return this.algID; }
+ }
+
+ public IStreamCalculator CreateCalculator()
+ {
+ ISigner sig = SignerUtilities.GetSigner(X509Utilities.GetSignatureName(algID));
+
+ sig.Init(false, publicKey);
+
+ return new VerifierCalculator(sig);
+ }
+ }
+
+ internal class VerifierCalculator : IStreamCalculator
+ {
+ private readonly ISigner sig;
+ private readonly Stream stream;
+
+ internal VerifierCalculator(ISigner sig)
+ {
+ this.sig = sig;
+ this.stream = new SignerBucket(sig);
+ }
+
+ public Stream Stream
+ {
+ get { return stream; }
+ }
+
+ public object GetResult()
+ {
+ return new VerifierResult(sig);
+ }
+ }
+
+ internal class VerifierResult : IVerifier
+ {
+ private readonly ISigner sig;
+
+ internal VerifierResult(ISigner sig)
+ {
+ this.sig = sig;
+ }
+
+ public bool IsVerified(byte[] signature)
+ {
+ return sig.VerifySignature(signature);
+ }
+
+ public bool IsVerified(byte[] signature, int off, int length)
+ {
+ byte[] sigBytes = new byte[length];
+
+ Array.Copy(signature, 0, sigBytes, off, sigBytes.Length);
+
+ return sig.VerifySignature(signature);
+ }
+ }
+
+ /// <summary>
+ /// Provider class which supports dynamic creation of signature verifiers.
+ /// </summary>
+ public class Asn1SignatureVerifierProvider: ISignatureVerifierProvider
+ {
+ private readonly AsymmetricKeyParameter publicKey;
+
+ /// <summary>
+ /// Base constructor - specify the public key to be used in verification.
+ /// </summary>
+ /// <param name="publicKey">The public key to be used in creating verifiers provided by this object.</param>
+ public Asn1SignatureVerifierProvider(AsymmetricKeyParameter publicKey)
+ {
+ this.publicKey = publicKey;
+ }
+
+ public ISignatureVerifier CreateSignatureVerifier(Object algorithmDetails)
+ {
+ return new Asn1SignatureVerifier ((AlgorithmIdentifier)algorithmDetails, publicKey);
+ }
+
+ /// <summary>
+ /// Allows enumeration of the signature names supported by the verifier provider.
+ /// </summary>
+ public IEnumerable SignatureAlgNames
+ {
+ get { return X509Utilities.GetAlgNames(); }
+ }
+ }
+}
+
diff --git a/crypto/src/crypto/tls/AbstractTlsContext.cs b/crypto/src/crypto/tls/AbstractTlsContext.cs
index e283ee58c..ae7efc64d 100644
--- a/crypto/src/crypto/tls/AbstractTlsContext.cs
+++ b/crypto/src/crypto/tls/AbstractTlsContext.cs
@@ -12,10 +12,21 @@ namespace Org.BouncyCastle.Crypto.Tls
{
private static long counter = Times.NanoTime();
+#if NETCF_1_0
+ private static object counterLock = new object();
+ private static long NextCounterValue()
+ {
+ lock (counterLock)
+ {
+ return ++counter;
+ }
+ }
+#else
private static long NextCounterValue()
{
return Interlocked.Increment(ref counter);
}
+#endif
private readonly IRandomGenerator mNonceRandom;
private readonly SecureRandom mSecureRandom;
@@ -26,7 +37,7 @@ namespace Org.BouncyCastle.Crypto.Tls
private TlsSession mSession = null;
private object mUserObject = null;
- internal AbstractTlsContext(SecureRandom secureRandom, SecurityParameters securityParameters)
+ internal AbstractTlsContext(SecureRandom secureRandom, SecurityParameters securityParameters)
{
IDigest d = TlsUtilities.CreateHash(HashAlgorithm.sha256);
byte[] seed = new byte[d.GetDigestSize()];
diff --git a/crypto/src/crypto/tls/ByteQueueStream.cs b/crypto/src/crypto/tls/ByteQueueStream.cs
new file mode 100644
index 000000000..bf603e006
--- /dev/null
+++ b/crypto/src/crypto/tls/ByteQueueStream.cs
@@ -0,0 +1,114 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ public class ByteQueueStream
+ : Stream
+ {
+ private readonly ByteQueue buffer;
+
+ public ByteQueueStream()
+ {
+ this.buffer = new ByteQueue();
+ }
+
+ public virtual int Available
+ {
+ get { return buffer.Available; }
+ }
+
+ public override bool CanRead
+ {
+ get { return true; }
+ }
+
+ public override bool CanSeek
+ {
+ get { return false; }
+ }
+
+ public override bool CanWrite
+ {
+ get { return true; }
+ }
+
+ public override void Close()
+ {
+ }
+
+ public override void Flush()
+ {
+ }
+
+ public override long Length
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public virtual int Peek(byte[] buf)
+ {
+ int bytesToRead = System.Math.Min(buffer.Available, buf.Length);
+ buffer.Read(buf, 0, bytesToRead, 0);
+ return bytesToRead;
+ }
+
+ public override long Position
+ {
+ get { throw new NotSupportedException(); }
+ set { throw new NotSupportedException(); }
+ }
+
+ public virtual int Read(byte[] buf)
+ {
+ return Read(buf, 0, buf.Length);
+ }
+
+ public override int Read(byte[] buf, int off, int len)
+ {
+ int bytesToRead = System.Math.Min(buffer.Available, len);
+ buffer.RemoveData(buf, off, bytesToRead, 0);
+ return bytesToRead;
+ }
+
+ public override int ReadByte()
+ {
+ if (buffer.Available == 0)
+ return -1;
+
+ return buffer.RemoveData(1, 0)[0] & 0xFF;
+ }
+
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override void SetLength(long value)
+ {
+ throw new NotSupportedException();
+ }
+
+ public virtual int Skip(int n)
+ {
+ int bytesToSkip = System.Math.Min(buffer.Available, n);
+ buffer.RemoveData(bytesToSkip);
+ return bytesToSkip;
+ }
+
+ public virtual void Write(byte[] buf)
+ {
+ buffer.AddData(buf, 0, buf.Length);
+ }
+
+ public override void Write(byte[] buf, int off, int len)
+ {
+ buffer.AddData(buf, off, len);
+ }
+
+ public override void WriteByte(byte b)
+ {
+ buffer.AddData(new byte[]{ b }, 0, 1);
+ }
+ }
+}
diff --git a/crypto/src/crypto/tls/RecordStream.cs b/crypto/src/crypto/tls/RecordStream.cs
index db5b158bc..6f3fc41c6 100644
--- a/crypto/src/crypto/tls/RecordStream.cs
+++ b/crypto/src/crypto/tls/RecordStream.cs
@@ -8,6 +8,11 @@ namespace Org.BouncyCastle.Crypto.Tls
{
private const int DEFAULT_PLAINTEXT_LIMIT = (1 << 14);
+ internal const int TLS_HEADER_SIZE = 5;
+ internal const int TLS_HEADER_TYPE_OFFSET = 0;
+ internal const int TLS_HEADER_VERSION_OFFSET = 1;
+ internal const int TLS_HEADER_LENGTH_OFFSET = 3;
+
private TlsProtocol mHandler;
private Stream mInput;
private Stream mOutput;
@@ -116,11 +121,11 @@ namespace Org.BouncyCastle.Crypto.Tls
internal virtual bool ReadRecord()
{
- byte[] recordHeader = TlsUtilities.ReadAllOrNothing(5, mInput);
+ byte[] recordHeader = TlsUtilities.ReadAllOrNothing(TLS_HEADER_SIZE, mInput);
if (recordHeader == null)
return false;
- byte type = TlsUtilities.ReadUint8(recordHeader, 0);
+ byte type = TlsUtilities.ReadUint8(recordHeader, TLS_HEADER_TYPE_OFFSET);
/*
* RFC 5246 6. If a TLS implementation receives an unexpected record type, it MUST send an
@@ -130,13 +135,13 @@ namespace Org.BouncyCastle.Crypto.Tls
if (!mRestrictReadVersion)
{
- int version = TlsUtilities.ReadVersionRaw(recordHeader, 1);
+ int version = TlsUtilities.ReadVersionRaw(recordHeader, TLS_HEADER_VERSION_OFFSET);
if ((version & 0xffffff00) != 0x0300)
throw new TlsFatalAlert(AlertDescription.illegal_parameter);
}
else
{
- ProtocolVersion version = TlsUtilities.ReadVersion(recordHeader, 1);
+ ProtocolVersion version = TlsUtilities.ReadVersion(recordHeader, TLS_HEADER_VERSION_OFFSET);
if (mReadVersion == null)
{
mReadVersion = version;
@@ -147,7 +152,7 @@ namespace Org.BouncyCastle.Crypto.Tls
}
}
- int length = TlsUtilities.ReadUint16(recordHeader, 3);
+ int length = TlsUtilities.ReadUint16(recordHeader, TLS_HEADER_LENGTH_OFFSET);
byte[] plaintext = DecodeAndVerify(type, mInput, length);
mHandler.ProcessRecord(type, plaintext, 0, plaintext.Length);
return true;
@@ -247,11 +252,11 @@ namespace Org.BouncyCastle.Crypto.Tls
*/
CheckLength(ciphertext.Length, mCiphertextLimit, AlertDescription.internal_error);
- byte[] record = new byte[ciphertext.Length + 5];
- TlsUtilities.WriteUint8(type, record, 0);
- TlsUtilities.WriteVersion(mWriteVersion, record, 1);
- TlsUtilities.WriteUint16(ciphertext.Length, record, 3);
- Array.Copy(ciphertext, 0, record, 5, ciphertext.Length);
+ byte[] record = new byte[ciphertext.Length + TLS_HEADER_SIZE];
+ TlsUtilities.WriteUint8(type, record, TLS_HEADER_TYPE_OFFSET);
+ TlsUtilities.WriteVersion(mWriteVersion, record, TLS_HEADER_VERSION_OFFSET);
+ TlsUtilities.WriteUint16(ciphertext.Length, record, TLS_HEADER_LENGTH_OFFSET);
+ Array.Copy(ciphertext, 0, record, TLS_HEADER_SIZE, ciphertext.Length);
mOutput.Write(record, 0, record.Length);
mOutput.Flush();
}
diff --git a/crypto/src/crypto/tls/TlsClientProtocol.cs b/crypto/src/crypto/tls/TlsClientProtocol.cs
index 7b8439acc..14c1cf4a4 100644
--- a/crypto/src/crypto/tls/TlsClientProtocol.cs
+++ b/crypto/src/crypto/tls/TlsClientProtocol.cs
@@ -21,21 +21,56 @@ namespace Org.BouncyCastle.Crypto.Tls
protected CertificateStatus mCertificateStatus = null;
protected CertificateRequest mCertificateRequest = null;
+ /**
+ * Constructor for blocking mode.
+ * @param stream The bi-directional stream of data to/from the server
+ * @param secureRandom Random number generator for various cryptographic functions
+ */
public TlsClientProtocol(Stream stream, SecureRandom secureRandom)
- : base(stream, secureRandom)
+ : base(stream, secureRandom)
{
}
+ /**
+ * Constructor for blocking mode.
+ * @param input The stream of data from the server
+ * @param output The stream of data to the server
+ * @param secureRandom Random number generator for various cryptographic functions
+ */
public TlsClientProtocol(Stream input, Stream output, SecureRandom secureRandom)
- : base(input, output, secureRandom)
+ : base(input, output, secureRandom)
+ {
+ }
+
+ /**
+ * Constructor for non-blocking mode.<br>
+ * <br>
+ * When data is received, use {@link #offerInput(java.nio.ByteBuffer)} to
+ * provide the received ciphertext, then use
+ * {@link #readInput(byte[], int, int)} to read the corresponding cleartext.<br>
+ * <br>
+ * Similarly, when data needs to be sent, use
+ * {@link #offerOutput(byte[], int, int)} to provide the cleartext, then use
+ * {@link #readOutput(byte[], int, int)} to get the corresponding
+ * ciphertext.
+ *
+ * @param secureRandom
+ * Random number generator for various cryptographic functions
+ */
+ public TlsClientProtocol(SecureRandom secureRandom)
+ : base(secureRandom)
{
}
/**
- * Initiates a TLS handshake in the role of client
+ * Initiates a TLS handshake in the role of client.<br>
+ * <br>
+ * In blocking mode, this will not return until the handshake is complete.
+ * In non-blocking mode, use {@link TlsPeer#NotifyHandshakeComplete()} to
+ * receive a callback when the handshake is complete.
*
* @param tlsClient The {@link TlsClient} to use for the handshake.
- * @throws IOException If handshake was not successful.
+ * @throws IOException If in blocking mode and handshake was not successful.
*/
public virtual void Connect(TlsClient tlsClient)
{
@@ -71,7 +106,7 @@ namespace Org.BouncyCastle.Crypto.Tls
SendClientHelloMessage();
this.mConnectionState = CS_CLIENT_HELLO;
- CompleteHandshake();
+ BlockForHandshake();
}
protected override void CleanupHandshake()
@@ -116,6 +151,7 @@ namespace Org.BouncyCastle.Crypto.Tls
this.mConnectionState = CS_CLIENT_FINISHED;
this.mConnectionState = CS_END;
+ CompleteHandshake();
return;
}
@@ -208,6 +244,8 @@ namespace Org.BouncyCastle.Crypto.Tls
ProcessFinishedMessage(buf);
this.mConnectionState = CS_SERVER_FINISHED;
this.mConnectionState = CS_END;
+
+ CompleteHandshake();
break;
}
default:
diff --git a/crypto/src/crypto/tls/TlsProtocol.cs b/crypto/src/crypto/tls/TlsProtocol.cs
index 8eb7beb3f..7acc34d3c 100644
--- a/crypto/src/crypto/tls/TlsProtocol.cs
+++ b/crypto/src/crypto/tls/TlsProtocol.cs
@@ -72,6 +72,10 @@ namespace Org.BouncyCastle.Crypto.Tls
protected bool mAllowCertificateStatus = false;
protected bool mExpectSessionTicket = false;
+ protected bool mBlocking = true;
+ protected ByteQueueStream mInputBuffers = null;
+ protected ByteQueueStream mOutputBuffer = null;
+
public TlsProtocol(Stream stream, SecureRandom secureRandom)
: this(stream, stream, secureRandom)
{
@@ -83,6 +87,15 @@ namespace Org.BouncyCastle.Crypto.Tls
this.mSecureRandom = secureRandom;
}
+ public TlsProtocol(SecureRandom secureRandom)
+ {
+ this.mBlocking = false;
+ this.mInputBuffers = new ByteQueueStream();
+ this.mOutputBuffer = new ByteQueueStream();
+ this.mRecordStream = new RecordStream(this, mInputBuffers, mOutputBuffer);
+ this.mSecureRandom = secureRandom;
+ }
+
protected abstract TlsContext Context { get; }
internal abstract AbstractTlsContext ContextAdmin { get; }
@@ -140,13 +153,10 @@ namespace Org.BouncyCastle.Crypto.Tls
this.mExpectSessionTicket = false;
}
- protected virtual void CompleteHandshake()
+ protected virtual void BlockForHandshake()
{
- try
+ if (mBlocking)
{
- /*
- * We will now read data, until we have completed the handshake.
- */
while (this.mConnectionState != CS_END)
{
if (this.mClosed)
@@ -156,7 +166,13 @@ namespace Org.BouncyCastle.Crypto.Tls
SafeReadRecord();
}
+ }
+ }
+ protected virtual void CompleteHandshake()
+ {
+ try
+ {
this.mRecordStream.FinaliseHandshake();
this.mSplitApplicationDataRecords = !TlsUtilities.IsTlsV11(Context);
@@ -168,7 +184,10 @@ namespace Org.BouncyCastle.Crypto.Tls
{
this.mAppDataReady = true;
- this.mTlsStream = new TlsStream(this);
+ if (mBlocking)
+ {
+ this.mTlsStream = new TlsStream(this);
+ }
}
if (this.mTlsSession != null)
@@ -573,9 +592,156 @@ namespace Org.BouncyCastle.Crypto.Tls
}
/// <summary>The secure bidirectional stream for this connection</summary>
+ /// <remarks>Only allowed in blocking mode.</remarks>
public virtual Stream Stream
{
- get { return this.mTlsStream; }
+ get
+ {
+ if (!mBlocking)
+ throw new InvalidOperationException("Cannot use Stream in non-blocking mode! Use OfferInput()/OfferOutput() instead.");
+ return this.mTlsStream;
+ }
+ }
+
+ /**
+ * Offer input from an arbitrary source. Only allowed in non-blocking mode.<br>
+ * <br>
+ * After this method returns, the input buffer is "owned" by this object. Other code
+ * must not attempt to do anything with it.<br>
+ * <br>
+ * This method will decrypt and process all records that are fully available.
+ * If only part of a record is available, the buffer will be retained until the
+ * remainder of the record is offered.<br>
+ * <br>
+ * If any records containing application data were processed, the decrypted data
+ * can be obtained using {@link #readInput(byte[], int, int)}. If any records
+ * containing protocol data were processed, a response may have been generated.
+ * You should always check to see if there is any available output after calling
+ * this method by calling {@link #getAvailableOutputBytes()}.
+ * @param input The input buffer to offer
+ * @throws IOException If an error occurs while decrypting or processing a record
+ */
+ public virtual void OfferInput(byte[] input)
+ {
+ if (mBlocking)
+ throw new InvalidOperationException("Cannot use OfferInput() in blocking mode! Use Stream instead.");
+ if (mClosed)
+ throw new IOException("Connection is closed, cannot accept any more input");
+
+ mInputBuffers.Write(input);
+
+ // loop while there are enough bytes to read the length of the next record
+ while (mInputBuffers.Available >= RecordStream.TLS_HEADER_SIZE)
+ {
+ byte[] header = new byte[RecordStream.TLS_HEADER_SIZE];
+ mInputBuffers.Peek(header);
+
+ int totalLength = TlsUtilities.ReadUint16(header, RecordStream.TLS_HEADER_LENGTH_OFFSET) + RecordStream.TLS_HEADER_SIZE;
+ if (mInputBuffers.Available < totalLength)
+ {
+ // not enough bytes to read a whole record
+ break;
+ }
+
+ SafeReadRecord();
+ }
+ }
+
+ /**
+ * Gets the amount of received application data. A call to {@link #readInput(byte[], int, int)}
+ * is guaranteed to be able to return at least this much data.<br>
+ * <br>
+ * Only allowed in non-blocking mode.
+ * @return The number of bytes of available application data
+ */
+ public virtual int GetAvailableInputBytes()
+ {
+ if (mBlocking)
+ throw new InvalidOperationException("Cannot use GetAvailableInputBytes() in blocking mode! Use ApplicationDataAvailable() instead.");
+
+ return ApplicationDataAvailable();
+ }
+
+ /**
+ * Retrieves received application data. Use {@link #getAvailableInputBytes()} to check
+ * how much application data is currently available. This method functions similarly to
+ * {@link InputStream#read(byte[], int, int)}, except that it never blocks. If no data
+ * is available, nothing will be copied and zero will be returned.<br>
+ * <br>
+ * Only allowed in non-blocking mode.
+ * @param buffer The buffer to hold the application data
+ * @param offset The start offset in the buffer at which the data is written
+ * @param length The maximum number of bytes to read
+ * @return The total number of bytes copied to the buffer. May be less than the
+ * length specified if the length was greater than the amount of available data.
+ */
+ public virtual int ReadInput(byte[] buffer, int offset, int length)
+ {
+ if (mBlocking)
+ throw new InvalidOperationException("Cannot use ReadInput() in blocking mode! Use Stream instead.");
+
+ return ReadApplicationData(buffer, offset, System.Math.Min(length, ApplicationDataAvailable()));
+ }
+
+ /**
+ * Offer output from an arbitrary source. Only allowed in non-blocking mode.<br>
+ * <br>
+ * After this method returns, the specified section of the buffer will have been
+ * processed. Use {@link #readOutput(byte[], int, int)} to get the bytes to
+ * transmit to the other peer.<br>
+ * <br>
+ * This method must not be called until after the handshake is complete! Attempting
+ * to call it before the handshake is complete will result in an exception.
+ * @param buffer The buffer containing application data to encrypt
+ * @param offset The offset at which to begin reading data
+ * @param length The number of bytes of data to read
+ * @throws IOException If an error occurs encrypting the data, or the handshake is not complete
+ */
+ public virtual void OfferOutput(byte[] buffer, int offset, int length)
+ {
+ if (mBlocking)
+ throw new InvalidOperationException("Cannot use OfferOutput() in blocking mode! Use Stream instead.");
+ if (!mAppDataReady)
+ throw new IOException("Application data cannot be sent until the handshake is complete!");
+
+ WriteData(buffer, offset, length);
+ }
+
+ /**
+ * Gets the amount of encrypted data available to be sent. A call to
+ * {@link #readOutput(byte[], int, int)} is guaranteed to be able to return at
+ * least this much data.<br>
+ * <br>
+ * Only allowed in non-blocking mode.
+ * @return The number of bytes of available encrypted data
+ */
+ public virtual int GetAvailableOutputBytes()
+ {
+ if (mBlocking)
+ throw new InvalidOperationException("Cannot use GetAvailableOutputBytes() in blocking mode! Use Stream instead.");
+
+ return mOutputBuffer.Available;
+ }
+
+ /**
+ * Retrieves encrypted data to be sent. Use {@link #getAvailableOutputBytes()} to check
+ * how much encrypted data is currently available. This method functions similarly to
+ * {@link InputStream#read(byte[], int, int)}, except that it never blocks. If no data
+ * is available, nothing will be copied and zero will be returned.<br>
+ * <br>
+ * Only allowed in non-blocking mode.
+ * @param buffer The buffer to hold the encrypted data
+ * @param offset The start offset in the buffer at which the data is written
+ * @param length The maximum number of bytes to read
+ * @return The total number of bytes copied to the buffer. May be less than the
+ * length specified if the length was greater than the amount of available data.
+ */
+ public virtual int ReadOutput(byte[] buffer, int offset, int length)
+ {
+ if (mBlocking)
+ throw new InvalidOperationException("Cannot use ReadOutput() in blocking mode! Use Stream instead.");
+
+ return mOutputBuffer.Read(buffer, offset, length);
}
/**
@@ -764,7 +930,7 @@ namespace Org.BouncyCastle.Crypto.Tls
mRecordStream.Flush();
}
- protected internal virtual bool IsClosed
+ public virtual bool IsClosed
{
get { return mClosed; }
}
diff --git a/crypto/src/crypto/tls/TlsServerProtocol.cs b/crypto/src/crypto/tls/TlsServerProtocol.cs
index b73cb5a30..27f7a1dfd 100644
--- a/crypto/src/crypto/tls/TlsServerProtocol.cs
+++ b/crypto/src/crypto/tls/TlsServerProtocol.cs
@@ -22,21 +22,57 @@ namespace Org.BouncyCastle.Crypto.Tls
protected short mClientCertificateType = -1;
protected TlsHandshakeHash mPrepareFinishHash = null;
+ /**
+ * Constructor for blocking mode.
+ * @param stream The bi-directional stream of data to/from the client
+ * @param output The stream of data to the client
+ * @param secureRandom Random number generator for various cryptographic functions
+ */
public TlsServerProtocol(Stream stream, SecureRandom secureRandom)
- : base(stream, secureRandom)
+ : base(stream, secureRandom)
{
}
+ /**
+ * Constructor for blocking mode.
+ * @param input The stream of data from the client
+ * @param output The stream of data to the client
+ * @param secureRandom Random number generator for various cryptographic functions
+ */
public TlsServerProtocol(Stream input, Stream output, SecureRandom secureRandom)
- : base(input, output, secureRandom)
+ : base(input, output, secureRandom)
+ {
+ }
+
+ /**
+ * Constructor for non-blocking mode.<br>
+ * <br>
+ * When data is received, use {@link #offerInput(java.nio.ByteBuffer)} to
+ * provide the received ciphertext, then use
+ * {@link #readInput(byte[], int, int)} to read the corresponding cleartext.<br>
+ * <br>
+ * Similarly, when data needs to be sent, use
+ * {@link #offerOutput(byte[], int, int)} to provide the cleartext, then use
+ * {@link #readOutput(byte[], int, int)} to get the corresponding
+ * ciphertext.
+ *
+ * @param secureRandom
+ * Random number generator for various cryptographic functions
+ */
+ public TlsServerProtocol(SecureRandom secureRandom)
+ : base(secureRandom)
{
}
/**
- * Receives a TLS handshake in the role of server
+ * Receives a TLS handshake in the role of server.<br>
+ * <br>
+ * In blocking mode, this will not return until the handshake is complete.
+ * In non-blocking mode, use {@link TlsPeer#notifyHandshakeComplete()} to
+ * receive a callback when the handshake is complete.
*
- * @param mTlsServer
- * @throws IOException If handshake was not successful.
+ * @param tlsServer
+ * @throws IOException If in blocking mode and handshake was not successful.
*/
public virtual void Accept(TlsServer tlsServer)
{
@@ -60,7 +96,7 @@ namespace Org.BouncyCastle.Crypto.Tls
this.mRecordStream.SetRestrictReadVersion(false);
- CompleteHandshake();
+ BlockForHandshake();
}
protected override void CleanupHandshake()
@@ -329,6 +365,8 @@ namespace Org.BouncyCastle.Crypto.Tls
SendFinishedMessage();
this.mConnectionState = CS_SERVER_FINISHED;
this.mConnectionState = CS_END;
+
+ CompleteHandshake();
break;
}
default:
diff --git a/crypto/src/math/ec/ECCurve.cs b/crypto/src/math/ec/ECCurve.cs
index 9fe9e32fd..40b46ce72 100644
--- a/crypto/src/math/ec/ECCurve.cs
+++ b/crypto/src/math/ec/ECCurve.cs
@@ -677,28 +677,110 @@ namespace Org.BouncyCastle.Math.EC
switch (this.CoordinateSystem)
{
- case COORD_LAMBDA_AFFINE:
- case COORD_LAMBDA_PROJECTIVE:
- {
- if (X.IsZero)
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
{
- if (!Y.Square().Equals(B))
- throw new ArgumentException();
+ if (X.IsZero)
+ {
+ if (!Y.Square().Equals(B))
+ throw new ArgumentException();
+ }
+ else
+ {
+ // Y becomes Lambda (X + Y/X) here
+ Y = Y.Divide(X).Add(X);
+ }
+ break;
}
- else
+ default:
{
- // Y becomes Lambda (X + Y/X) here
- Y = Y.Divide(X).Add(X);
+ break;
}
- break;
}
- default:
+
+ return CreateRawPoint(X, Y, withCompression);
+ }
+
+ protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
+ {
+ ECFieldElement xp = FromBigInteger(X1), yp = null;
+ if (xp.IsZero)
{
- break;
+ yp = B.Sqrt();
}
+ else
+ {
+ ECFieldElement beta = xp.Square().Invert().Multiply(B).Add(A).Add(xp);
+ ECFieldElement z = SolveQuadradicEquation(beta);
+
+ if (z != null)
+ {
+ if (z.TestBitZero() != (yTilde == 1))
+ {
+ z = z.AddOne();
+ }
+
+ switch (this.CoordinateSystem)
+ {
+ case COORD_LAMBDA_AFFINE:
+ case COORD_LAMBDA_PROJECTIVE:
+ {
+ yp = z.Add(xp);
+ break;
+ }
+ default:
+ {
+ yp = z.Multiply(xp);
+ break;
+ }
+ }
+ }
}
- return CreateRawPoint(X, Y, withCompression);
+ if (yp == null)
+ throw new ArgumentException("Invalid point compression");
+
+ return CreateRawPoint(xp, yp, true);
+ }
+
+ /**
+ * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
+ * D.1.6) The other solution is <code>z + 1</code>.
+ *
+ * @param beta
+ * The value to solve the qradratic equation for.
+ * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
+ * <code>null</code> if no solution exists.
+ */
+ private ECFieldElement SolveQuadradicEquation(ECFieldElement beta)
+ {
+ if (beta.IsZero)
+ return beta;
+
+ ECFieldElement gamma, z, zeroElement = FromBigInteger(BigInteger.Zero);
+
+ int m = FieldSize;
+ Random rand = new Random();
+ do
+ {
+ ECFieldElement t = FromBigInteger(new BigInteger(m, rand));
+ z = zeroElement;
+ ECFieldElement w = beta;
+ for (int i = 1; i < m; i++)
+ {
+ ECFieldElement w2 = w.Square();
+ z = z.Square().Add(w2.Multiply(t));
+ w = w2.Add(beta);
+ }
+ if (!w.IsZero)
+ {
+ return null;
+ }
+ gamma = z.Square().Add(z);
+ }
+ while (gamma.IsZero);
+
+ return z;
}
/**
@@ -994,92 +1076,6 @@ namespace Org.BouncyCastle.Math.EC
get { return m_infinity; }
}
- protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement xp = FromBigInteger(X1), yp = null;
- if (xp.IsZero)
- {
- yp = m_b.Sqrt();
- }
- else
- {
- ECFieldElement beta = xp.Square().Invert().Multiply(B).Add(A).Add(xp);
- ECFieldElement z = SolveQuadradicEquation(beta);
-
- if (z != null)
- {
- if (z.TestBitZero() != (yTilde == 1))
- {
- z = z.AddOne();
- }
-
- switch (this.CoordinateSystem)
- {
- case COORD_LAMBDA_AFFINE:
- case COORD_LAMBDA_PROJECTIVE:
- {
- yp = z.Add(xp);
- break;
- }
- default:
- {
- yp = z.Multiply(xp);
- break;
- }
- }
- }
- }
-
- if (yp == null)
- throw new ArgumentException("Invalid point compression");
-
- return CreateRawPoint(xp, yp, true);
- }
-
- /**
- * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
- * D.1.6) The other solution is <code>z + 1</code>.
- *
- * @param beta
- * The value to solve the qradratic equation for.
- * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
- * <code>null</code> if no solution exists.
- */
- private ECFieldElement SolveQuadradicEquation(ECFieldElement beta)
- {
- if (beta.IsZero)
- {
- return beta;
- }
-
- ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
-
- ECFieldElement z = null;
- ECFieldElement gamma = null;
-
- Random rand = new Random();
- do
- {
- ECFieldElement t = FromBigInteger(new BigInteger(m, rand));
- z = zeroElement;
- ECFieldElement w = beta;
- for (int i = 1; i < m; i++)
- {
- ECFieldElement w2 = w.Square();
- z = z.Square().Add(w2.Multiply(t));
- w = w2.Add(beta);
- }
- if (!w.IsZero)
- {
- return null;
- }
- gamma = z.Square().Add(z);
- }
- while (gamma.IsZero);
-
- return z;
- }
-
public int M
{
get { return m; }
diff --git a/crypto/src/math/ec/custom/sec/SecT113R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT113R1Curve.cs
index 04e69e2a8..2705c94aa 100644
--- a/crypto/src/math/ec/custom/sec/SecT113R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT113R1Curve.cs
@@ -65,101 +65,11 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
return new SecT113R1Point(this, x, y, zs, withCompression);
}
- public override bool IsKoblitz
+ public override bool IsKoblitz
{
get { return false; }
}
- /**
- * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
- *
- * @param yTilde
- * ~yp, an indication bit for the decompression of yp.
- * @param X1
- * The field element xp.
- * @return the decompressed point.
- */
- protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = FromBigInteger(X1), y = null;
- if (x.IsZero)
- {
- y = B.Sqrt();
- }
- else
- {
- ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
- ECFieldElement z = SolveQuadraticEquation(beta);
- if (z != null)
- {
- if (z.TestBitZero() != (yTilde == 1))
- {
- z = z.AddOne();
- }
-
- switch (this.CoordinateSystem)
- {
- case COORD_LAMBDA_AFFINE:
- case COORD_LAMBDA_PROJECTIVE:
- {
- y = z.Add(x);
- break;
- }
- default:
- {
- y = z.Multiply(x);
- break;
- }
- }
- }
- }
-
- if (y == null)
- throw new ArgumentException("Invalid point compression");
-
- return this.CreateRawPoint(x, y, true);
- }
-
- /**
- * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
- * D.1.6) The other solution is <code>z + 1</code>.
- *
- * @param beta
- * The value to solve the quadratic equation for.
- * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
- * <code>null</code> if no solution exists.
- */
- private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
- {
- if (beta.IsZero)
- return beta;
-
- ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
-
- ECFieldElement z = null;
- ECFieldElement gamma = null;
-
- Random rand = new Random();
- do
- {
- ECFieldElement t = FromBigInteger(new BigInteger(113, rand));
- z = zeroElement;
- ECFieldElement w = beta;
- for (int i = 1; i < 113; i++)
- {
- ECFieldElement w2 = w.Square();
- z = z.Square().Add(w2.Multiply(t));
- w = w2.Add(beta);
- }
- if (!w.IsZero)
- return null;
- gamma = z.Square().Add(z);
- }
- while (gamma.IsZero);
-
- return z;
- }
-
public virtual int M
{
get { return 113; }
diff --git a/crypto/src/math/ec/custom/sec/SecT113R2Curve.cs b/crypto/src/math/ec/custom/sec/SecT113R2Curve.cs
index a02db6b25..abfd26d5b 100644
--- a/crypto/src/math/ec/custom/sec/SecT113R2Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT113R2Curve.cs
@@ -70,98 +70,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
get { return false; }
}
- /**
- * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
- *
- * @param yTilde
- * ~yp, an indication bit for the decompression of yp.
- * @param X1
- * The field element xp.
- * @return the decompressed point.
- */
- protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = FromBigInteger(X1), y = null;
- if (x.IsZero)
- {
- y = B.Sqrt();
- }
- else
- {
- ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
- ECFieldElement z = SolveQuadraticEquation(beta);
- if (z != null)
- {
- if (z.TestBitZero() != (yTilde == 1))
- {
- z = z.AddOne();
- }
-
- switch (this.CoordinateSystem)
- {
- case COORD_LAMBDA_AFFINE:
- case COORD_LAMBDA_PROJECTIVE:
- {
- y = z.Add(x);
- break;
- }
- default:
- {
- y = z.Multiply(x);
- break;
- }
- }
- }
- }
-
- if (y == null)
- throw new ArgumentException("Invalid point compression");
-
- return this.CreateRawPoint(x, y, true);
- }
-
- /**
- * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
- * D.1.6) The other solution is <code>z + 1</code>.
- *
- * @param beta
- * The value to solve the quadratic equation for.
- * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
- * <code>null</code> if no solution exists.
- */
- private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
- {
- if (beta.IsZero)
- {
- return beta;
- }
-
- ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
-
- ECFieldElement z = null;
- ECFieldElement gamma = null;
-
- Random rand = new Random();
- do
- {
- ECFieldElement t = FromBigInteger(new BigInteger(113, rand));
- z = zeroElement;
- ECFieldElement w = beta;
- for (int i = 1; i < 113; i++)
- {
- ECFieldElement w2 = w.Square();
- z = z.Square().Add(w2.Multiply(t));
- w = w2.Add(beta);
- }
- if (!w.IsZero)
- return null;
- gamma = z.Square().Add(z);
- }
- while (gamma.IsZero);
-
- return z;
- }
-
public virtual int M
{
get { return 113; }
diff --git a/crypto/src/math/ec/custom/sec/SecT131R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT131R1Curve.cs
index 789e3c0c3..b73964c39 100644
--- a/crypto/src/math/ec/custom/sec/SecT131R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT131R1Curve.cs
@@ -70,96 +70,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
get { return false; }
}
- /**
- * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
- *
- * @param yTilde
- * ~yp, an indication bit for the decompression of yp.
- * @param X1
- * The field element xp.
- * @return the decompressed point.
- */
- protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = FromBigInteger(X1), y = null;
- if (x.IsZero)
- {
- y = B.Sqrt();
- }
- else
- {
- ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
- ECFieldElement z = SolveQuadraticEquation(beta);
- if (z != null)
- {
- if (z.TestBitZero() != (yTilde == 1))
- {
- z = z.AddOne();
- }
-
- switch (this.CoordinateSystem)
- {
- case COORD_LAMBDA_AFFINE:
- case COORD_LAMBDA_PROJECTIVE:
- {
- y = z.Add(x);
- break;
- }
- default:
- {
- y = z.Multiply(x);
- break;
- }
- }
- }
- }
-
- if (y == null)
- throw new ArgumentException("Invalid point compression");
-
- return this.CreateRawPoint(x, y, true);
- }
-
- /**
- * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
- * D.1.6) The other solution is <code>z + 1</code>.
- *
- * @param beta
- * The value to solve the quadratic equation for.
- * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
- * <code>null</code> if no solution exists.
- */
- private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
- {
- if (beta.IsZero)
- return beta;
-
- ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
-
- ECFieldElement z = null;
- ECFieldElement gamma = null;
-
- Random rand = new Random();
- do
- {
- ECFieldElement t = FromBigInteger(new BigInteger(131, rand));
- z = zeroElement;
- ECFieldElement w = beta;
- for (int i = 1; i < 131; i++)
- {
- ECFieldElement w2 = w.Square();
- z = z.Square().Add(w2.Multiply(t));
- w = w2.Add(beta);
- }
- if (!w.IsZero)
- return null;
- gamma = z.Square().Add(z);
- }
- while (gamma.IsZero);
-
- return z;
- }
-
public virtual int M
{
get { return 131; }
diff --git a/crypto/src/math/ec/custom/sec/SecT131R2Curve.cs b/crypto/src/math/ec/custom/sec/SecT131R2Curve.cs
index 2004f84ca..724921c94 100644
--- a/crypto/src/math/ec/custom/sec/SecT131R2Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT131R2Curve.cs
@@ -70,98 +70,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
get { return false; }
}
- /**
- * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
- *
- * @param yTilde
- * ~yp, an indication bit for the decompression of yp.
- * @param X1
- * The field element xp.
- * @return the decompressed point.
- */
- protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = FromBigInteger(X1), y = null;
- if (x.IsZero)
- {
- y = B.Sqrt();
- }
- else
- {
- ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
- ECFieldElement z = SolveQuadraticEquation(beta);
- if (z != null)
- {
- if (z.TestBitZero() != (yTilde == 1))
- {
- z = z.AddOne();
- }
-
- switch (this.CoordinateSystem)
- {
- case COORD_LAMBDA_AFFINE:
- case COORD_LAMBDA_PROJECTIVE:
- {
- y = z.Add(x);
- break;
- }
- default:
- {
- y = z.Multiply(x);
- break;
- }
- }
- }
- }
-
- if (y == null)
- throw new ArgumentException("Invalid point compression");
-
- return this.CreateRawPoint(x, y, true);
- }
-
- /**
- * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
- * D.1.6) The other solution is <code>z + 1</code>.
- *
- * @param beta
- * The value to solve the quadratic equation for.
- * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
- * <code>null</code> if no solution exists.
- */
- private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
- {
- if (beta.IsZero)
- {
- return beta;
- }
-
- ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
-
- ECFieldElement z = null;
- ECFieldElement gamma = null;
-
- Random rand = new Random();
- do
- {
- ECFieldElement t = FromBigInteger(new BigInteger(131, rand));
- z = zeroElement;
- ECFieldElement w = beta;
- for (int i = 1; i < 131; i++)
- {
- ECFieldElement w2 = w.Square();
- z = z.Square().Add(w2.Multiply(t));
- w = w2.Add(beta);
- }
- if (!w.IsZero)
- return null;
- gamma = z.Square().Add(z);
- }
- while (gamma.IsZero);
-
- return z;
- }
-
public virtual int M
{
get { return 131; }
diff --git a/crypto/src/math/ec/custom/sec/SecT163K1Curve.cs b/crypto/src/math/ec/custom/sec/SecT163K1Curve.cs
index 1cfd09e1c..68ff646ca 100644
--- a/crypto/src/math/ec/custom/sec/SecT163K1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT163K1Curve.cs
@@ -76,96 +76,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
get { return true; }
}
- /**
- * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
- *
- * @param yTilde
- * ~yp, an indication bit for the decompression of yp.
- * @param X1
- * The field element xp.
- * @return the decompressed point.
- */
- protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = FromBigInteger(X1), y = null;
- if (x.IsZero)
- {
- y = B.Sqrt();
- }
- else
- {
- ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
- ECFieldElement z = SolveQuadraticEquation(beta);
- if (z != null)
- {
- if (z.TestBitZero() != (yTilde == 1))
- {
- z = z.AddOne();
- }
-
- switch (this.CoordinateSystem)
- {
- case COORD_LAMBDA_AFFINE:
- case COORD_LAMBDA_PROJECTIVE:
- {
- y = z.Add(x);
- break;
- }
- default:
- {
- y = z.Multiply(x);
- break;
- }
- }
- }
- }
-
- if (y == null)
- throw new ArgumentException("Invalid point compression");
-
- return this.CreateRawPoint(x, y, true);
- }
-
- /**
- * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
- * D.1.6) The other solution is <code>z + 1</code>.
- *
- * @param beta
- * The value to solve the quadratic equation for.
- * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
- * <code>null</code> if no solution exists.
- */
- private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
- {
- if (beta.IsZero)
- return beta;
-
- ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
-
- ECFieldElement z = null;
- ECFieldElement gamma = null;
-
- Random rand = new Random();
- do
- {
- ECFieldElement t = FromBigInteger(new BigInteger(163, rand));
- z = zeroElement;
- ECFieldElement w = beta;
- for (int i = 1; i < 163; i++)
- {
- ECFieldElement w2 = w.Square();
- z = z.Square().Add(w2.Multiply(t));
- w = w2.Add(beta);
- }
- if (!w.IsZero)
- return null;
- gamma = z.Square().Add(z);
- }
- while (gamma.IsZero);
-
- return z;
- }
-
public virtual int M
{
get { return 163; }
diff --git a/crypto/src/math/ec/custom/sec/SecT163R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT163R1Curve.cs
index fc18e1094..8ae58ccef 100644
--- a/crypto/src/math/ec/custom/sec/SecT163R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT163R1Curve.cs
@@ -70,98 +70,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
get { return false; }
}
- /**
- * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
- *
- * @param yTilde
- * ~yp, an indication bit for the decompression of yp.
- * @param X1
- * The field element xp.
- * @return the decompressed point.
- */
- protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = FromBigInteger(X1), y = null;
- if (x.IsZero)
- {
- y = B.Sqrt();
- }
- else
- {
- ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
- ECFieldElement z = SolveQuadraticEquation(beta);
- if (z != null)
- {
- if (z.TestBitZero() != (yTilde == 1))
- {
- z = z.AddOne();
- }
-
- switch (this.CoordinateSystem)
- {
- case COORD_LAMBDA_AFFINE:
- case COORD_LAMBDA_PROJECTIVE:
- {
- y = z.Add(x);
- break;
- }
- default:
- {
- y = z.Multiply(x);
- break;
- }
- }
- }
- }
-
- if (y == null)
- throw new ArgumentException("Invalid point compression");
-
- return this.CreateRawPoint(x, y, true);
- }
-
- /**
- * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
- * D.1.6) The other solution is <code>z + 1</code>.
- *
- * @param beta
- * The value to solve the quadratic equation for.
- * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
- * <code>null</code> if no solution exists.
- */
- private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
- {
- if (beta.IsZero)
- {
- return beta;
- }
-
- ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
-
- ECFieldElement z = null;
- ECFieldElement gamma = null;
-
- Random rand = new Random();
- do
- {
- ECFieldElement t = FromBigInteger(new BigInteger(163, rand));
- z = zeroElement;
- ECFieldElement w = beta;
- for (int i = 1; i < 163; i++)
- {
- ECFieldElement w2 = w.Square();
- z = z.Square().Add(w2.Multiply(t));
- w = w2.Add(beta);
- }
- if (!w.IsZero)
- return null;
- gamma = z.Square().Add(z);
- }
- while (gamma.IsZero);
-
- return z;
- }
-
public virtual int M
{
get { return 163; }
diff --git a/crypto/src/math/ec/custom/sec/SecT163R2Curve.cs b/crypto/src/math/ec/custom/sec/SecT163R2Curve.cs
index 9efe11c3e..5a4fa5ad1 100644
--- a/crypto/src/math/ec/custom/sec/SecT163R2Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT163R2Curve.cs
@@ -70,96 +70,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
get { return false; }
}
- /**
- * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
- *
- * @param yTilde
- * ~yp, an indication bit for the decompression of yp.
- * @param X1
- * The field element xp.
- * @return the decompressed point.
- */
- protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = FromBigInteger(X1), y = null;
- if (x.IsZero)
- {
- y = B.Sqrt();
- }
- else
- {
- ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
- ECFieldElement z = SolveQuadraticEquation(beta);
- if (z != null)
- {
- if (z.TestBitZero() != (yTilde == 1))
- {
- z = z.AddOne();
- }
-
- switch (this.CoordinateSystem)
- {
- case COORD_LAMBDA_AFFINE:
- case COORD_LAMBDA_PROJECTIVE:
- {
- y = z.Add(x);
- break;
- }
- default:
- {
- y = z.Multiply(x);
- break;
- }
- }
- }
- }
-
- if (y == null)
- throw new ArgumentException("Invalid point compression");
-
- return this.CreateRawPoint(x, y, true);
- }
-
- /**
- * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
- * D.1.6) The other solution is <code>z + 1</code>.
- *
- * @param beta
- * The value to solve the quadratic equation for.
- * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
- * <code>null</code> if no solution exists.
- */
- private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
- {
- if (beta.IsZero)
- return beta;
-
- ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
-
- ECFieldElement z = null;
- ECFieldElement gamma = null;
-
- Random rand = new Random();
- do
- {
- ECFieldElement t = FromBigInteger(new BigInteger(163, rand));
- z = zeroElement;
- ECFieldElement w = beta;
- for (int i = 1; i < 163; i++)
- {
- ECFieldElement w2 = w.Square();
- z = z.Square().Add(w2.Multiply(t));
- w = w2.Add(beta);
- }
- if (!w.IsZero)
- return null;
- gamma = z.Square().Add(z);
- }
- while (gamma.IsZero);
-
- return z;
- }
-
public virtual int M
{
get { return 163; }
diff --git a/crypto/src/math/ec/custom/sec/SecT193R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT193R1Curve.cs
index 802954b01..a2cb5a8ac 100644
--- a/crypto/src/math/ec/custom/sec/SecT193R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT193R1Curve.cs
@@ -70,98 +70,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
get { return false; }
}
- /**
- * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
- *
- * @param yTilde
- * ~yp, an indication bit for the decompression of yp.
- * @param X1
- * The field element xp.
- * @return the decompressed point.
- */
- protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = FromBigInteger(X1), y = null;
- if (x.IsZero)
- {
- y = B.Sqrt();
- }
- else
- {
- ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
- ECFieldElement z = SolveQuadraticEquation(beta);
- if (z != null)
- {
- if (z.TestBitZero() != (yTilde == 1))
- {
- z = z.AddOne();
- }
-
- switch (this.CoordinateSystem)
- {
- case COORD_LAMBDA_AFFINE:
- case COORD_LAMBDA_PROJECTIVE:
- {
- y = z.Add(x);
- break;
- }
- default:
- {
- y = z.Multiply(x);
- break;
- }
- }
- }
- }
-
- if (y == null)
- throw new ArgumentException("Invalid point compression");
-
- return this.CreateRawPoint(x, y, true);
- }
-
- /**
- * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
- * D.1.6) The other solution is <code>z + 1</code>.
- *
- * @param beta
- * The value to solve the quadratic equation for.
- * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
- * <code>null</code> if no solution exists.
- */
- private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
- {
- if (beta.IsZero)
- {
- return beta;
- }
-
- ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
-
- ECFieldElement z = null;
- ECFieldElement gamma = null;
-
- Random rand = new Random();
- do
- {
- ECFieldElement t = FromBigInteger(new BigInteger(193, rand));
- z = zeroElement;
- ECFieldElement w = beta;
- for (int i = 1; i < 193; i++)
- {
- ECFieldElement w2 = w.Square();
- z = z.Square().Add(w2.Multiply(t));
- w = w2.Add(beta);
- }
- if (!w.IsZero)
- return null;
- gamma = z.Square().Add(z);
- }
- while (gamma.IsZero);
-
- return z;
- }
-
public virtual int M
{
get { return 193; }
diff --git a/crypto/src/math/ec/custom/sec/SecT193R2Curve.cs b/crypto/src/math/ec/custom/sec/SecT193R2Curve.cs
index b5345730c..1c84a3eac 100644
--- a/crypto/src/math/ec/custom/sec/SecT193R2Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT193R2Curve.cs
@@ -70,98 +70,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
get { return false; }
}
- /**
- * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
- *
- * @param yTilde
- * ~yp, an indication bit for the decompression of yp.
- * @param X1
- * The field element xp.
- * @return the decompressed point.
- */
- protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = FromBigInteger(X1), y = null;
- if (x.IsZero)
- {
- y = B.Sqrt();
- }
- else
- {
- ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
- ECFieldElement z = SolveQuadraticEquation(beta);
- if (z != null)
- {
- if (z.TestBitZero() != (yTilde == 1))
- {
- z = z.AddOne();
- }
-
- switch (this.CoordinateSystem)
- {
- case COORD_LAMBDA_AFFINE:
- case COORD_LAMBDA_PROJECTIVE:
- {
- y = z.Add(x);
- break;
- }
- default:
- {
- y = z.Multiply(x);
- break;
- }
- }
- }
- }
-
- if (y == null)
- throw new ArgumentException("Invalid point compression");
-
- return this.CreateRawPoint(x, y, true);
- }
-
- /**
- * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
- * D.1.6) The other solution is <code>z + 1</code>.
- *
- * @param beta
- * The value to solve the quadratic equation for.
- * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
- * <code>null</code> if no solution exists.
- */
- private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
- {
- if (beta.IsZero)
- {
- return beta;
- }
-
- ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
-
- ECFieldElement z = null;
- ECFieldElement gamma = null;
-
- Random rand = new Random();
- do
- {
- ECFieldElement t = FromBigInteger(new BigInteger(193, rand));
- z = zeroElement;
- ECFieldElement w = beta;
- for (int i = 1; i < 193; i++)
- {
- ECFieldElement w2 = w.Square();
- z = z.Square().Add(w2.Multiply(t));
- w = w2.Add(beta);
- }
- if (!w.IsZero)
- return null;
- gamma = z.Square().Add(z);
- }
- while (gamma.IsZero);
-
- return z;
- }
-
public virtual int M
{
get { return 193; }
diff --git a/crypto/src/math/ec/custom/sec/SecT233K1Curve.cs b/crypto/src/math/ec/custom/sec/SecT233K1Curve.cs
index 8768eaa81..72935913d 100644
--- a/crypto/src/math/ec/custom/sec/SecT233K1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT233K1Curve.cs
@@ -76,98 +76,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
get { return true; }
}
- /**
- * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
- *
- * @param yTilde
- * ~yp, an indication bit for the decompression of yp.
- * @param X1
- * The field element xp.
- * @return the decompressed point.
- */
- protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = FromBigInteger(X1), y = null;
- if (x.IsZero)
- {
- y = B.Sqrt();
- }
- else
- {
- ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
- ECFieldElement z = SolveQuadraticEquation(beta);
- if (z != null)
- {
- if (z.TestBitZero() != (yTilde == 1))
- {
- z = z.AddOne();
- }
-
- switch (this.CoordinateSystem)
- {
- case COORD_LAMBDA_AFFINE:
- case COORD_LAMBDA_PROJECTIVE:
- {
- y = z.Add(x);
- break;
- }
- default:
- {
- y = z.Multiply(x);
- break;
- }
- }
- }
- }
-
- if (y == null)
- throw new ArgumentException("Invalid point compression");
-
- return this.CreateRawPoint(x, y, true);
- }
-
- /**
- * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
- * D.1.6) The other solution is <code>z + 1</code>.
- *
- * @param beta
- * The value to solve the quadratic equation for.
- * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
- * <code>null</code> if no solution exists.
- */
- private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
- {
- if (beta.IsZero)
- {
- return beta;
- }
-
- ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
-
- ECFieldElement z = null;
- ECFieldElement gamma = null;
-
- Random rand = new Random();
- do
- {
- ECFieldElement t = FromBigInteger(new BigInteger(233, rand));
- z = zeroElement;
- ECFieldElement w = beta;
- for (int i = 1; i < 233; i++)
- {
- ECFieldElement w2 = w.Square();
- z = z.Square().Add(w2.Multiply(t));
- w = w2.Add(beta);
- }
- if (!w.IsZero)
- return null;
- gamma = z.Square().Add(z);
- }
- while (gamma.IsZero);
-
- return z;
- }
-
public virtual int M
{
get { return 233; }
diff --git a/crypto/src/math/ec/custom/sec/SecT233R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT233R1Curve.cs
index 92795b8a7..db6e6e1d4 100644
--- a/crypto/src/math/ec/custom/sec/SecT233R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT233R1Curve.cs
@@ -70,96 +70,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
get { return false; }
}
- /**
- * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
- *
- * @param yTilde
- * ~yp, an indication bit for the decompression of yp.
- * @param X1
- * The field element xp.
- * @return the decompressed point.
- */
- protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = FromBigInteger(X1), y = null;
- if (x.IsZero)
- {
- y = B.Sqrt();
- }
- else
- {
- ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
- ECFieldElement z = SolveQuadraticEquation(beta);
- if (z != null)
- {
- if (z.TestBitZero() != (yTilde == 1))
- {
- z = z.AddOne();
- }
-
- switch (this.CoordinateSystem)
- {
- case COORD_LAMBDA_AFFINE:
- case COORD_LAMBDA_PROJECTIVE:
- {
- y = z.Add(x);
- break;
- }
- default:
- {
- y = z.Multiply(x);
- break;
- }
- }
- }
- }
-
- if (y == null)
- throw new ArgumentException("Invalid point compression");
-
- return this.CreateRawPoint(x, y, true);
- }
-
- /**
- * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
- * D.1.6) The other solution is <code>z + 1</code>.
- *
- * @param beta
- * The value to solve the quadratic equation for.
- * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
- * <code>null</code> if no solution exists.
- */
- private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
- {
- if (beta.IsZero)
- return beta;
-
- ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
-
- ECFieldElement z = null;
- ECFieldElement gamma = null;
-
- Random rand = new Random();
- do
- {
- ECFieldElement t = FromBigInteger(new BigInteger(233, rand));
- z = zeroElement;
- ECFieldElement w = beta;
- for (int i = 1; i < 233; i++)
- {
- ECFieldElement w2 = w.Square();
- z = z.Square().Add(w2.Multiply(t));
- w = w2.Add(beta);
- }
- if (!w.IsZero)
- return null;
- gamma = z.Square().Add(z);
- }
- while (gamma.IsZero);
-
- return z;
- }
-
public virtual int M
{
get { return 233; }
diff --git a/crypto/src/math/ec/custom/sec/SecT239K1Curve.cs b/crypto/src/math/ec/custom/sec/SecT239K1Curve.cs
index 2c73d941f..a499d48b4 100644
--- a/crypto/src/math/ec/custom/sec/SecT239K1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT239K1Curve.cs
@@ -76,96 +76,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
get { return true; }
}
- /**
- * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
- *
- * @param yTilde
- * ~yp, an indication bit for the decompression of yp.
- * @param X1
- * The field element xp.
- * @return the decompressed point.
- */
- protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = FromBigInteger(X1), y = null;
- if (x.IsZero)
- {
- y = B.Sqrt();
- }
- else
- {
- ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
- ECFieldElement z = SolveQuadraticEquation(beta);
- if (z != null)
- {
- if (z.TestBitZero() != (yTilde == 1))
- {
- z = z.AddOne();
- }
-
- switch (this.CoordinateSystem)
- {
- case COORD_LAMBDA_AFFINE:
- case COORD_LAMBDA_PROJECTIVE:
- {
- y = z.Add(x);
- break;
- }
- default:
- {
- y = z.Multiply(x);
- break;
- }
- }
- }
- }
-
- if (y == null)
- throw new ArgumentException("Invalid point compression");
-
- return this.CreateRawPoint(x, y, true);
- }
-
- /**
- * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
- * D.1.6) The other solution is <code>z + 1</code>.
- *
- * @param beta
- * The value to solve the quadratic equation for.
- * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
- * <code>null</code> if no solution exists.
- */
- private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
- {
- if (beta.IsZero)
- return beta;
-
- ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
-
- ECFieldElement z = null;
- ECFieldElement gamma = null;
-
- Random rand = new Random();
- do
- {
- ECFieldElement t = FromBigInteger(new BigInteger(239, rand));
- z = zeroElement;
- ECFieldElement w = beta;
- for (int i = 1; i < 239; i++)
- {
- ECFieldElement w2 = w.Square();
- z = z.Square().Add(w2.Multiply(t));
- w = w2.Add(beta);
- }
- if (!w.IsZero)
- return null;
- gamma = z.Square().Add(z);
- }
- while (gamma.IsZero);
-
- return z;
- }
-
public virtual int M
{
get { return 239; }
diff --git a/crypto/src/math/ec/custom/sec/SecT283K1Curve.cs b/crypto/src/math/ec/custom/sec/SecT283K1Curve.cs
index 42414401f..4053287ec 100644
--- a/crypto/src/math/ec/custom/sec/SecT283K1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT283K1Curve.cs
@@ -76,96 +76,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
get { return true; }
}
- /**
- * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
- *
- * @param yTilde
- * ~yp, an indication bit for the decompression of yp.
- * @param X1
- * The field element xp.
- * @return the decompressed point.
- */
- protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = FromBigInteger(X1), y = null;
- if (x.IsZero)
- {
- y = B.Sqrt();
- }
- else
- {
- ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
- ECFieldElement z = SolveQuadraticEquation(beta);
- if (z != null)
- {
- if (z.TestBitZero() != (yTilde == 1))
- {
- z = z.AddOne();
- }
-
- switch (this.CoordinateSystem)
- {
- case COORD_LAMBDA_AFFINE:
- case COORD_LAMBDA_PROJECTIVE:
- {
- y = z.Add(x);
- break;
- }
- default:
- {
- y = z.Multiply(x);
- break;
- }
- }
- }
- }
-
- if (y == null)
- throw new ArgumentException("Invalid point compression");
-
- return this.CreateRawPoint(x, y, true);
- }
-
- /**
- * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
- * D.1.6) The other solution is <code>z + 1</code>.
- *
- * @param beta
- * The value to solve the quadratic equation for.
- * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
- * <code>null</code> if no solution exists.
- */
- private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
- {
- if (beta.IsZero)
- return beta;
-
- ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
-
- ECFieldElement z = null;
- ECFieldElement gamma = null;
-
- Random rand = new Random();
- do
- {
- ECFieldElement t = FromBigInteger(new BigInteger(283, rand));
- z = zeroElement;
- ECFieldElement w = beta;
- for (int i = 1; i < 283; i++)
- {
- ECFieldElement w2 = w.Square();
- z = z.Square().Add(w2.Multiply(t));
- w = w2.Add(beta);
- }
- if (!w.IsZero)
- return null;
- gamma = z.Square().Add(z);
- }
- while (gamma.IsZero);
-
- return z;
- }
-
public virtual int M
{
get { return 283; }
diff --git a/crypto/src/math/ec/custom/sec/SecT283R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT283R1Curve.cs
index d8c462eeb..e659675ce 100644
--- a/crypto/src/math/ec/custom/sec/SecT283R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT283R1Curve.cs
@@ -70,96 +70,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
get { return false; }
}
- /**
- * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
- *
- * @param yTilde
- * ~yp, an indication bit for the decompression of yp.
- * @param X1
- * The field element xp.
- * @return the decompressed point.
- */
- protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = FromBigInteger(X1), y = null;
- if (x.IsZero)
- {
- y = B.Sqrt();
- }
- else
- {
- ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
- ECFieldElement z = SolveQuadraticEquation(beta);
- if (z != null)
- {
- if (z.TestBitZero() != (yTilde == 1))
- {
- z = z.AddOne();
- }
-
- switch (this.CoordinateSystem)
- {
- case COORD_LAMBDA_AFFINE:
- case COORD_LAMBDA_PROJECTIVE:
- {
- y = z.Add(x);
- break;
- }
- default:
- {
- y = z.Multiply(x);
- break;
- }
- }
- }
- }
-
- if (y == null)
- throw new ArgumentException("Invalid point compression");
-
- return this.CreateRawPoint(x, y, true);
- }
-
- /**
- * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
- * D.1.6) The other solution is <code>z + 1</code>.
- *
- * @param beta
- * The value to solve the quadratic equation for.
- * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
- * <code>null</code> if no solution exists.
- */
- private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
- {
- if (beta.IsZero)
- return beta;
-
- ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
-
- ECFieldElement z = null;
- ECFieldElement gamma = null;
-
- Random rand = new Random();
- do
- {
- ECFieldElement t = FromBigInteger(new BigInteger(283, rand));
- z = zeroElement;
- ECFieldElement w = beta;
- for (int i = 1; i < 283; i++)
- {
- ECFieldElement w2 = w.Square();
- z = z.Square().Add(w2.Multiply(t));
- w = w2.Add(beta);
- }
- if (!w.IsZero)
- return null;
- gamma = z.Square().Add(z);
- }
- while (gamma.IsZero);
-
- return z;
- }
-
public virtual int M
{
get { return 283; }
diff --git a/crypto/src/math/ec/custom/sec/SecT409K1Curve.cs b/crypto/src/math/ec/custom/sec/SecT409K1Curve.cs
index edfe1a293..4f573553e 100644
--- a/crypto/src/math/ec/custom/sec/SecT409K1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT409K1Curve.cs
@@ -76,96 +76,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
get { return true; }
}
- /**
- * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
- *
- * @param yTilde
- * ~yp, an indication bit for the decompression of yp.
- * @param X1
- * The field element xp.
- * @return the decompressed point.
- */
- protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = FromBigInteger(X1), y = null;
- if (x.IsZero)
- {
- y = B.Sqrt();
- }
- else
- {
- ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
- ECFieldElement z = SolveQuadraticEquation(beta);
- if (z != null)
- {
- if (z.TestBitZero() != (yTilde == 1))
- {
- z = z.AddOne();
- }
-
- switch (this.CoordinateSystem)
- {
- case COORD_LAMBDA_AFFINE:
- case COORD_LAMBDA_PROJECTIVE:
- {
- y = z.Add(x);
- break;
- }
- default:
- {
- y = z.Multiply(x);
- break;
- }
- }
- }
- }
-
- if (y == null)
- throw new ArgumentException("Invalid point compression");
-
- return this.CreateRawPoint(x, y, true);
- }
-
- /**
- * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
- * D.1.6) The other solution is <code>z + 1</code>.
- *
- * @param beta
- * The value to solve the quadratic equation for.
- * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
- * <code>null</code> if no solution exists.
- */
- private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
- {
- if (beta.IsZero)
- return beta;
-
- ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
-
- ECFieldElement z = null;
- ECFieldElement gamma = null;
-
- Random rand = new Random();
- do
- {
- ECFieldElement t = FromBigInteger(new BigInteger(409, rand));
- z = zeroElement;
- ECFieldElement w = beta;
- for (int i = 1; i < 409; i++)
- {
- ECFieldElement w2 = w.Square();
- z = z.Square().Add(w2.Multiply(t));
- w = w2.Add(beta);
- }
- if (!w.IsZero)
- return null;
- gamma = z.Square().Add(z);
- }
- while (gamma.IsZero);
-
- return z;
- }
-
public virtual int M
{
get { return 409; }
diff --git a/crypto/src/math/ec/custom/sec/SecT409R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT409R1Curve.cs
index e679094ad..9212fb5d2 100644
--- a/crypto/src/math/ec/custom/sec/SecT409R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT409R1Curve.cs
@@ -70,96 +70,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
get { return false; }
}
- /**
- * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
- *
- * @param yTilde
- * ~yp, an indication bit for the decompression of yp.
- * @param X1
- * The field element xp.
- * @return the decompressed point.
- */
- protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = FromBigInteger(X1), y = null;
- if (x.IsZero)
- {
- y = B.Sqrt();
- }
- else
- {
- ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
- ECFieldElement z = SolveQuadraticEquation(beta);
- if (z != null)
- {
- if (z.TestBitZero() != (yTilde == 1))
- {
- z = z.AddOne();
- }
-
- switch (this.CoordinateSystem)
- {
- case COORD_LAMBDA_AFFINE:
- case COORD_LAMBDA_PROJECTIVE:
- {
- y = z.Add(x);
- break;
- }
- default:
- {
- y = z.Multiply(x);
- break;
- }
- }
- }
- }
-
- if (y == null)
- throw new ArgumentException("Invalid point compression");
-
- return this.CreateRawPoint(x, y, true);
- }
-
- /**
- * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
- * D.1.6) The other solution is <code>z + 1</code>.
- *
- * @param beta
- * The value to solve the quadratic equation for.
- * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
- * <code>null</code> if no solution exists.
- */
- private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
- {
- if (beta.IsZero)
- return beta;
-
- ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
-
- ECFieldElement z = null;
- ECFieldElement gamma = null;
-
- Random rand = new Random();
- do
- {
- ECFieldElement t = FromBigInteger(new BigInteger(409, rand));
- z = zeroElement;
- ECFieldElement w = beta;
- for (int i = 1; i < 409; i++)
- {
- ECFieldElement w2 = w.Square();
- z = z.Square().Add(w2.Multiply(t));
- w = w2.Add(beta);
- }
- if (!w.IsZero)
- return null;
- gamma = z.Square().Add(z);
- }
- while (gamma.IsZero);
-
- return z;
- }
-
public virtual int M
{
get { return 409; }
diff --git a/crypto/src/math/ec/custom/sec/SecT571K1Curve.cs b/crypto/src/math/ec/custom/sec/SecT571K1Curve.cs
index fb136c967..f5806f09c 100644
--- a/crypto/src/math/ec/custom/sec/SecT571K1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT571K1Curve.cs
@@ -76,98 +76,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
get { return true; }
}
- /**
- * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
- *
- * @param yTilde
- * ~yp, an indication bit for the decompression of yp.
- * @param X1
- * The field element xp.
- * @return the decompressed point.
- */
- protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = FromBigInteger(X1), y = null;
- if (x.IsZero)
- {
- y = B.Sqrt();
- }
- else
- {
- ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
- ECFieldElement z = SolveQuadraticEquation(beta);
- if (z != null)
- {
- if (z.TestBitZero() != (yTilde == 1))
- {
- z = z.AddOne();
- }
-
- switch (this.CoordinateSystem)
- {
- case COORD_LAMBDA_AFFINE:
- case COORD_LAMBDA_PROJECTIVE:
- {
- y = z.Add(x);
- break;
- }
- default:
- {
- y = z.Multiply(x);
- break;
- }
- }
- }
- }
-
- if (y == null)
- throw new ArgumentException("Invalid point compression");
-
- return this.CreateRawPoint(x, y, true);
- }
-
- /**
- * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
- * D.1.6) The other solution is <code>z + 1</code>.
- *
- * @param beta
- * The value to solve the quadratic equation for.
- * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
- * <code>null</code> if no solution exists.
- */
- private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
- {
- if (beta.IsZero)
- {
- return beta;
- }
-
- ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
-
- ECFieldElement z = null;
- ECFieldElement gamma = null;
-
- Random rand = new Random();
- do
- {
- ECFieldElement t = FromBigInteger(new BigInteger(571, rand));
- z = zeroElement;
- ECFieldElement w = beta;
- for (int i = 1; i < 571; i++)
- {
- ECFieldElement w2 = w.Square();
- z = z.Square().Add(w2.Multiply(t));
- w = w2.Add(beta);
- }
- if (!w.IsZero)
- return null;
- gamma = z.Square().Add(z);
- }
- while (gamma.IsZero);
-
- return z;
- }
-
public virtual int M
{
get { return 571; }
diff --git a/crypto/src/math/ec/custom/sec/SecT571R1Curve.cs b/crypto/src/math/ec/custom/sec/SecT571R1Curve.cs
index 05d58863e..082afa5bd 100644
--- a/crypto/src/math/ec/custom/sec/SecT571R1Curve.cs
+++ b/crypto/src/math/ec/custom/sec/SecT571R1Curve.cs
@@ -74,97 +74,6 @@ namespace Org.BouncyCastle.Math.EC.Custom.Sec
get { return false; }
}
- /**
- * Decompresses a compressed point P = (xp, yp) (X9.62 s 4.2.2).
- *
- * @param yTilde
- * ~yp, an indication bit for the decompression of yp.
- * @param X1
- * The field element xp.
- * @return the decompressed point.
- */
- protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
- {
- ECFieldElement x = FromBigInteger(X1), y = null;
- if (x.IsZero)
- {
- // y = B.Sqrt();
- y = SecT571R1_B_SQRT;
- }
- else
- {
- ECFieldElement beta = x.Square().Invert().Multiply(B).Add(A).Add(x);
- ECFieldElement z = SolveQuadraticEquation(beta);
- if (z != null)
- {
- if (z.TestBitZero() != (yTilde == 1))
- {
- z = z.AddOne();
- }
-
- switch (this.CoordinateSystem)
- {
- case COORD_LAMBDA_AFFINE:
- case COORD_LAMBDA_PROJECTIVE:
- {
- y = z.Add(x);
- break;
- }
- default:
- {
- y = z.Multiply(x);
- break;
- }
- }
- }
- }
-
- if (y == null)
- throw new ArgumentException("Invalid point compression");
-
- return this.CreateRawPoint(x, y, true);
- }
-
- /**
- * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
- * D.1.6) The other solution is <code>z + 1</code>.
- *
- * @param beta
- * The value to solve the quadratic equation for.
- * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
- * <code>null</code> if no solution exists.
- */
- private ECFieldElement SolveQuadraticEquation(ECFieldElement beta)
- {
- if (beta.IsZero)
- return beta;
-
- ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
-
- ECFieldElement z = null;
- ECFieldElement gamma = null;
-
- Random rand = new Random();
- do
- {
- ECFieldElement t = FromBigInteger(new BigInteger(571, rand));
- z = zeroElement;
- ECFieldElement w = beta;
- for (int i = 1; i < 571; i++)
- {
- ECFieldElement w2 = w.Square();
- z = z.Square().Add(w2.Multiply(t));
- w = w2.Add(beta);
- }
- if (!w.IsZero)
- return null;
- gamma = z.Square().Add(z);
- }
- while (gamma.IsZero);
-
- return z;
- }
-
public virtual int M
{
get { return 571; }
diff --git a/crypto/src/openpgp/PgpEncryptedDataGenerator.cs b/crypto/src/openpgp/PgpEncryptedDataGenerator.cs
index f46f99d37..2a2e63961 100644
--- a/crypto/src/openpgp/PgpEncryptedDataGenerator.cs
+++ b/crypto/src/openpgp/PgpEncryptedDataGenerator.cs
@@ -3,10 +3,13 @@ using System.Collections;
using System.Diagnostics;
using System.IO;
+using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
@@ -79,70 +82,133 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
: EncMethod
{
internal PgpPublicKey pubKey;
- internal BigInteger[] data;
+ internal byte[][] data;
- internal PubMethod(
- PgpPublicKey pubKey)
+ internal PubMethod(PgpPublicKey pubKey)
{
this.pubKey = pubKey;
}
- public override void AddSessionInfo(
- byte[] si,
+ public override void AddSessionInfo(
+ byte[] sessionInfo,
SecureRandom random)
{
- IBufferedCipher c;
+ byte[] encryptedSessionInfo = EncryptSessionInfo(sessionInfo, random);
+
+ this.data = ProcessSessionInfo(encryptedSessionInfo);
+ }
- switch (pubKey.Algorithm)
+ private byte[] EncryptSessionInfo(byte[] sessionInfo, SecureRandom random)
+ {
+ if (pubKey.Algorithm != PublicKeyAlgorithmTag.ECDH)
{
- case PublicKeyAlgorithmTag.RsaEncrypt:
- case PublicKeyAlgorithmTag.RsaGeneral:
- c = CipherUtilities.GetCipher("RSA//PKCS1Padding");
- break;
- case PublicKeyAlgorithmTag.ElGamalEncrypt:
- case PublicKeyAlgorithmTag.ElGamalGeneral:
- c = CipherUtilities.GetCipher("ElGamal/ECB/PKCS1Padding");
- break;
- case PublicKeyAlgorithmTag.Dsa:
- throw new PgpException("Can't use DSA for encryption.");
- case PublicKeyAlgorithmTag.ECDsa:
- throw new PgpException("Can't use ECDSA for encryption.");
- default:
- throw new PgpException("unknown asymmetric algorithm: " + pubKey.Algorithm);
+ IBufferedCipher c;
+ switch (pubKey.Algorithm)
+ {
+ case PublicKeyAlgorithmTag.RsaEncrypt:
+ case PublicKeyAlgorithmTag.RsaGeneral:
+ c = CipherUtilities.GetCipher("RSA//PKCS1Padding");
+ break;
+ case PublicKeyAlgorithmTag.ElGamalEncrypt:
+ case PublicKeyAlgorithmTag.ElGamalGeneral:
+ c = CipherUtilities.GetCipher("ElGamal/ECB/PKCS1Padding");
+ break;
+ case PublicKeyAlgorithmTag.Dsa:
+ throw new PgpException("Can't use DSA for encryption.");
+ case PublicKeyAlgorithmTag.ECDsa:
+ throw new PgpException("Can't use ECDSA for encryption.");
+ default:
+ throw new PgpException("unknown asymmetric algorithm: " + pubKey.Algorithm);
+ }
+
+ AsymmetricKeyParameter akp = pubKey.GetKey();
+ c.Init(true, new ParametersWithRandom(akp, random));
+ return c.DoFinal(sessionInfo);
}
- AsymmetricKeyParameter akp = pubKey.GetKey();
+ ECDHPublicBcpgKey ecKey = (ECDHPublicBcpgKey)pubKey.PublicKeyPacket.Key;
+
+ // Generate the ephemeral key pair
+ IAsymmetricCipherKeyPairGenerator gen = GeneratorUtilities.GetKeyPairGenerator("ECDH");
+ gen.Init(new ECKeyGenerationParameters(ecKey.CurveOid, random));
+
+ AsymmetricCipherKeyPair ephKp = gen.GenerateKeyPair();
+ ECPrivateKeyParameters ephPriv = (ECPrivateKeyParameters)ephKp.Private;
+ ECPublicKeyParameters ephPub = (ECPublicKeyParameters)ephKp.Public;
+
+ ECPublicKeyParameters pub = (ECPublicKeyParameters)pubKey.GetKey();
+ ECPoint S = pub.Q.Multiply(ephPriv.D).Normalize();
+
+ KeyParameter key = new KeyParameter(Rfc6637Utilities.CreateKey(pubKey.PublicKeyPacket, S));
+
+ IWrapper w = PgpUtilities.CreateWrapper(ecKey.SymmetricKeyAlgorithm);
+ w.Init(true, new ParametersWithRandom(key, random));
+
+ byte[] paddedSessionData = PgpPad.PadSessionData(sessionInfo);
+
+ byte[] C = w.Wrap(paddedSessionData, 0, paddedSessionData.Length);
+ byte[] VB = new MPInteger(new BigInteger(1, ephPub.Q.GetEncoded(false))).GetEncoded();
- c.Init(true, new ParametersWithRandom(akp, random));
+ byte[] rv = new byte[VB.Length + 1 + C.Length];
- byte[] encKey = c.DoFinal(si);
+ Array.Copy(VB, 0, rv, 0, VB.Length);
+ rv[VB.Length] = (byte)C.Length;
+ Array.Copy(C, 0, rv, VB.Length + 1, C.Length);
- switch (pubKey.Algorithm)
+ return rv;
+ }
+
+ private byte[][] ProcessSessionInfo(byte[] encryptedSessionInfo)
+ {
+ byte[][] data;
+
+ switch (pubKey.Algorithm)
{
- case PublicKeyAlgorithmTag.RsaEncrypt:
- case PublicKeyAlgorithmTag.RsaGeneral:
- data = new BigInteger[]{ new BigInteger(1, encKey) };
- break;
- case PublicKeyAlgorithmTag.ElGamalEncrypt:
- case PublicKeyAlgorithmTag.ElGamalGeneral:
- int halfLength = encKey.Length / 2;
- data = new BigInteger[]
- {
- new BigInteger(1, encKey, 0, halfLength),
- new BigInteger(1, encKey, halfLength, halfLength)
- };
- break;
- default:
- throw new PgpException("unknown asymmetric algorithm: " + encAlgorithm);
+ case PublicKeyAlgorithmTag.RsaEncrypt:
+ case PublicKeyAlgorithmTag.RsaGeneral:
+ data = new byte[][] { ConvertToEncodedMpi(encryptedSessionInfo) };
+ break;
+ case PublicKeyAlgorithmTag.ElGamalEncrypt:
+ case PublicKeyAlgorithmTag.ElGamalGeneral:
+ int halfLength = encryptedSessionInfo.Length / 2;
+ byte[] b1 = new byte[halfLength];
+ byte[] b2 = new byte[halfLength];
+
+ Array.Copy(encryptedSessionInfo, 0, b1, 0, halfLength);
+ Array.Copy(encryptedSessionInfo, halfLength, b2, 0, halfLength);
+
+ data = new byte[][] {
+ ConvertToEncodedMpi(b1),
+ ConvertToEncodedMpi(b2),
+ };
+ break;
+ case PublicKeyAlgorithmTag.ECDH:
+ data = new byte[][]{ encryptedSessionInfo };
+ break;
+ default:
+ throw new PgpException("unknown asymmetric algorithm: " + pubKey.Algorithm);
}
+
+ return data;
}
- public override void Encode(BcpgOutputStream pOut)
+ private byte[] ConvertToEncodedMpi(byte[] encryptedSessionInfo)
+ {
+ try
+ {
+ return new MPInteger(new BigInteger(1, encryptedSessionInfo)).GetEncoded();
+ }
+ catch (IOException e)
+ {
+ throw new PgpException("Invalid MPI encoding: " + e.Message, e);
+ }
+ }
+
+ public override void Encode(BcpgOutputStream pOut)
{
- PublicKeyEncSessionPacket pk = new PublicKeyEncSessionPacket(
- pubKey.KeyId, pubKey.Algorithm, data);
+ PublicKeyEncSessionPacket pk = new PublicKeyEncSessionPacket(pubKey.KeyId, pubKey.Algorithm, data);
- pOut.WritePacket(pk);
+ pOut.WritePacket(pk);
}
}
diff --git a/crypto/src/openpgp/PgpKeyPair.cs b/crypto/src/openpgp/PgpKeyPair.cs
index 6efb03a42..9cf78fa6f 100644
--- a/crypto/src/openpgp/PgpKeyPair.cs
+++ b/crypto/src/openpgp/PgpKeyPair.cs
@@ -34,7 +34,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
DateTime time)
{
this.pub = new PgpPublicKey(algorithm, pubKey, time);
- this.priv = new PgpPrivateKey(privKey, pub.KeyId);
+ this.priv = new PgpPrivateKey(pub.KeyId, pub.PublicKeyPacket, privKey);
}
/// <summary>Create a key pair from a PgpPrivateKey and a PgpPublicKey.</summary>
diff --git a/crypto/src/openpgp/PgpKeyRingGenerator.cs b/crypto/src/openpgp/PgpKeyRingGenerator.cs
index e85fc2eef..92ea394a2 100644
--- a/crypto/src/openpgp/PgpKeyRingGenerator.cs
+++ b/crypto/src/openpgp/PgpKeyRingGenerator.cs
@@ -15,6 +15,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
private IList keys = Platform.CreateArrayList();
private string id;
private SymmetricKeyAlgorithmTag encAlgorithm;
+ private HashAlgorithmTag hashAlgorithm;
private int certificationLevel;
private char[] passPhrase;
private bool useSha1;
@@ -84,6 +85,45 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
keys.Add(new PgpSecretKey(certificationLevel, masterKey, id, encAlgorithm, passPhrase, useSha1, hashedPackets, unhashedPackets, rand));
}
+ /// <summary>
+ /// Create a new key ring generator.
+ /// </summary>
+ /// <param name="certificationLevel">The certification level for keys on this ring.</param>
+ /// <param name="masterKey">The master key pair.</param>
+ /// <param name="id">The id to be associated with the ring.</param>
+ /// <param name="encAlgorithm">The algorithm to be used to protect secret keys.</param>
+ /// <param name="hashAlgorithm">The hash algorithm.</param>
+ /// <param name="passPhrase">The passPhrase to be used to protect secret keys.</param>
+ /// <param name="useSha1">Checksum the secret keys with SHA1 rather than the older 16 bit checksum.</param>
+ /// <param name="hashedPackets">Packets to be included in the certification hash.</param>
+ /// <param name="unhashedPackets">Packets to be attached unhashed to the certification.</param>
+ /// <param name="rand">input secured random.</param>
+ public PgpKeyRingGenerator(
+ int certificationLevel,
+ PgpKeyPair masterKey,
+ string id,
+ SymmetricKeyAlgorithmTag encAlgorithm,
+ HashAlgorithmTag hashAlgorithm,
+ char[] passPhrase,
+ bool useSha1,
+ PgpSignatureSubpacketVector hashedPackets,
+ PgpSignatureSubpacketVector unhashedPackets,
+ SecureRandom rand)
+ {
+ this.certificationLevel = certificationLevel;
+ this.masterKey = masterKey;
+ this.id = id;
+ this.encAlgorithm = encAlgorithm;
+ this.passPhrase = passPhrase;
+ this.useSha1 = useSha1;
+ this.hashedPacketVector = hashedPackets;
+ this.unhashedPacketVector = unhashedPackets;
+ this.rand = rand;
+ this.hashAlgorithm = hashAlgorithm;
+
+ keys.Add(new PgpSecretKey(certificationLevel, masterKey, id, encAlgorithm, hashAlgorithm, passPhrase, useSha1, hashedPackets, unhashedPackets, rand));
+ }
+
/// <summary>Add a subkey to the key ring to be generated with default certification.</summary>
public void AddSubKey(
PgpKeyPair keyPair)
@@ -91,6 +131,17 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
AddSubKey(keyPair, this.hashedPacketVector, this.unhashedPacketVector);
}
+
+ /// <summary>
+ /// Add a subkey to the key ring to be generated with default certification.
+ /// </summary>
+ /// <param name="keyPair">The key pair.</param>
+ /// <param name="hashAlgorithm">The hash algorithm.</param>
+ public void AddSubKey(PgpKeyPair keyPair, HashAlgorithmTag hashAlgorithm)
+ {
+ this.AddSubKey(keyPair, this.hashedPacketVector, this.unhashedPacketVector, hashAlgorithm);
+ }
+
/// <summary>
/// Add a subkey with specific hashed and unhashed packets associated with it and
/// default certification.
@@ -133,6 +184,50 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
}
}
+ /// <summary>
+ /// Add a subkey with specific hashed and unhashed packets associated with it and
+ /// default certification.
+ /// </summary>
+ /// <param name="keyPair">Public/private key pair.</param>
+ /// <param name="hashedPackets">Hashed packet values to be included in certification.</param>
+ /// <param name="unhashedPackets">Unhashed packets values to be included in certification.</param>
+ /// <param name="hashAlgorithm">The hash algorithm.</param>
+ /// <exception cref="Org.BouncyCastle.Bcpg.OpenPgp.PgpException">exception adding subkey: </exception>
+ /// <exception cref="PgpException"></exception>
+ public void AddSubKey(
+ PgpKeyPair keyPair,
+ PgpSignatureSubpacketVector hashedPackets,
+ PgpSignatureSubpacketVector unhashedPackets,
+ HashAlgorithmTag hashAlgorithm)
+ {
+ try
+ {
+ var sGen = new PgpSignatureGenerator(masterKey.PublicKey.Algorithm, hashAlgorithm);
+
+ //
+ // Generate the certification
+ //
+ sGen.InitSign(PgpSignature.SubkeyBinding, masterKey.PrivateKey);
+
+ sGen.SetHashedSubpackets(hashedPackets);
+ sGen.SetUnhashedSubpackets(unhashedPackets);
+
+ IList subSigs = Platform.CreateArrayList();
+ subSigs.Add(sGen.GenerateCertification(masterKey.PublicKey, keyPair.PublicKey));
+
+ keys.Add(new PgpSecretKey(keyPair.PrivateKey, new PgpPublicKey(keyPair.PublicKey, null, subSigs), encAlgorithm, passPhrase, useSha1, rand));
+ }
+ catch (PgpException)
+ {
+ throw;
+ }
+ catch (Exception e)
+ {
+ throw new PgpException("exception adding subkey: ", e);
+ }
+ }
+
+
/// <summary>Return the secret key ring.</summary>
public PgpSecretKeyRing GenerateSecretKeyRing()
{
diff --git a/crypto/src/openpgp/PgpPad.cs b/crypto/src/openpgp/PgpPad.cs
new file mode 100644
index 000000000..48f7f2f44
--- /dev/null
+++ b/crypto/src/openpgp/PgpPad.cs
@@ -0,0 +1,45 @@
+using System;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+ /// <remarks>Padding functions.</remarks>
+ public sealed class PgpPad
+ {
+ private PgpPad()
+ {
+ }
+
+ public static byte[] PadSessionData(byte[] sessionInfo)
+ {
+ byte[] result = new byte[40];
+
+ Array.Copy(sessionInfo, 0, result, 0, sessionInfo.Length);
+
+ byte padValue = (byte)(result.Length - sessionInfo.Length);
+
+ for (int i = sessionInfo.Length; i != result.Length; i++)
+ {
+ result[i] = padValue;
+ }
+
+ return result;
+ }
+
+ public static byte[] UnpadSessionData(byte[] encoded)
+ {
+ byte padValue = encoded[encoded.Length - 1];
+
+ for (int i = encoded.Length - padValue; i != encoded.Length; i++)
+ {
+ if (encoded[i] != padValue)
+ throw new PgpException("bad padding found in session data");
+ }
+
+ byte[] taggedKey = new byte[encoded.Length - padValue];
+
+ Array.Copy(encoded, 0, taggedKey, 0, taggedKey.Length);
+
+ return taggedKey;
+ }
+ }
+}
diff --git a/crypto/src/openpgp/PgpPrivateKey.cs b/crypto/src/openpgp/PgpPrivateKey.cs
index 154c87cd7..61487a5b2 100644
--- a/crypto/src/openpgp/PgpPrivateKey.cs
+++ b/crypto/src/openpgp/PgpPrivateKey.cs
@@ -7,33 +7,42 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
/// <remarks>General class to contain a private key for use with other OpenPGP objects.</remarks>
public class PgpPrivateKey
{
- private readonly long keyId;
+ private readonly long keyID;
+ private readonly PublicKeyPacket publicKeyPacket;
private readonly AsymmetricKeyParameter privateKey;
- /// <summary>
- /// Create a PgpPrivateKey from a regular private key and the ID of its
- /// associated public key.
+ /// <summary>
+ /// Create a PgpPrivateKey from a keyID, the associated public data packet, and a regular private key.
/// </summary>
- /// <param name="privateKey">Private key to use.</param>
- /// <param name="keyId">ID of the corresponding public key.</param>
- public PgpPrivateKey(
- AsymmetricKeyParameter privateKey,
- long keyId)
+ /// <param name="keyID">ID of the corresponding public key.</param>
+ /// <param name="publicKeyPacket">the public key data packet to be associated with this private key.</param>
+ /// <param name="privateKey">the private key data packet to be associated with this private key.</param>
+ public PgpPrivateKey(
+ long keyID,
+ PublicKeyPacket publicKeyPacket,
+ AsymmetricKeyParameter privateKey)
{
if (!privateKey.IsPrivate)
throw new ArgumentException("Expected a private key", "privateKey");
- this.privateKey = privateKey;
- this.keyId = keyId;
+ this.keyID = keyID;
+ this.publicKeyPacket = publicKeyPacket;
+ this.privateKey = privateKey;
}
- /// <summary>The keyId associated with the contained private key.</summary>
+ /// <summary>The keyId associated with the contained private key.</summary>
public long KeyId
{
- get { return keyId; }
+ get { return keyID; }
}
- /// <summary>The contained private key.</summary>
+ /// <summary>The public key packet associated with this private key, if available.</summary>
+ public PublicKeyPacket PublicKeyPacket
+ {
+ get { return publicKeyPacket; }
+ }
+
+ /// <summary>The contained private key.</summary>
public AsymmetricKeyParameter Key
{
get { return privateKey; }
diff --git a/crypto/src/openpgp/PgpPublicKey.cs b/crypto/src/openpgp/PgpPublicKey.cs
index 5bde2c8fe..904e29913 100644
--- a/crypto/src/openpgp/PgpPublicKey.cs
+++ b/crypto/src/openpgp/PgpPublicKey.cs
@@ -2,10 +2,14 @@ using System;
using System.Collections;
using System.IO;
+using Org.BouncyCastle.Asn1.Sec;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.IO;
using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Collections;
@@ -15,6 +19,54 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
/// <remarks>General class to handle a PGP public key object.</remarks>
public class PgpPublicKey
{
+ public static byte[] CalculateFingerprint(PublicKeyPacket publicPk)
+ {
+ IBcpgKey key = publicPk.Key;
+ IDigest digest;
+
+ if (publicPk.Version <= 3)
+ {
+ RsaPublicBcpgKey rK = (RsaPublicBcpgKey)key;
+
+ try
+ {
+ digest = DigestUtilities.GetDigest("MD5");
+ UpdateDigest(digest, rK.Modulus);
+ UpdateDigest(digest, rK.PublicExponent);
+ }
+ catch (Exception e)
+ {
+ throw new PgpException("can't encode key components: " + e.Message, e);
+ }
+ }
+ else
+ {
+ try
+ {
+ byte[] kBytes = publicPk.GetEncodedContents();
+
+ digest = DigestUtilities.GetDigest("SHA1");
+
+ digest.Update(0x99);
+ digest.Update((byte)(kBytes.Length >> 8));
+ digest.Update((byte)kBytes.Length);
+ digest.BlockUpdate(kBytes, 0, kBytes.Length);
+ }
+ catch (Exception e)
+ {
+ throw new PgpException("can't encode key components: " + e.Message, e);
+ }
+ }
+
+ return DigestUtilities.DoFinal(digest);
+ }
+
+ private static void UpdateDigest(IDigest d, BigInteger b)
+ {
+ byte[] bytes = b.ToByteArrayUnsigned();
+ d.BlockUpdate(bytes, 0, bytes.Length);
+ }
+
private static readonly int[] MasterKeyCertificationTypes = new int[]
{
PgpSignature.PositiveCertification,
@@ -39,51 +91,17 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
{
IBcpgKey key = publicPk.Key;
+ this.fingerprint = CalculateFingerprint(publicPk);
+
if (publicPk.Version <= 3)
{
RsaPublicBcpgKey rK = (RsaPublicBcpgKey) key;
this.keyId = rK.Modulus.LongValue;
-
- try
- {
- IDigest digest = DigestUtilities.GetDigest("MD5");
-
- byte[] bytes = rK.Modulus.ToByteArrayUnsigned();
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- bytes = rK.PublicExponent.ToByteArrayUnsigned();
- digest.BlockUpdate(bytes, 0, bytes.Length);
-
- this.fingerprint = DigestUtilities.DoFinal(digest);
- }
- //catch (NoSuchAlgorithmException)
- catch (Exception e)
- {
- throw new IOException("can't find MD5", e);
- }
-
this.keyStrength = rK.Modulus.BitLength;
}
else
{
- byte[] kBytes = publicPk.GetEncodedContents();
-
- try
- {
- IDigest digest = DigestUtilities.GetDigest("SHA1");
-
- digest.Update(0x99);
- digest.Update((byte)(kBytes.Length >> 8));
- digest.Update((byte)kBytes.Length);
- digest.BlockUpdate(kBytes, 0, kBytes.Length);
- this.fingerprint = DigestUtilities.DoFinal(digest);
- }
- catch (Exception e)
- {
- throw new IOException("can't find SHA1", e);
- }
-
this.keyId = (long)(((ulong)fingerprint[fingerprint.Length - 8] << 56)
| ((ulong)fingerprint[fingerprint.Length - 7] << 48)
| ((ulong)fingerprint[fingerprint.Length - 6] << 40)
@@ -107,7 +125,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
}
else if (key is ECPublicBcpgKey)
{
- this.keyStrength = ECNamedCurveTable.GetByOid(((ECPublicBcpgKey)key).CurveOid).Curve.FieldSize;
+ this.keyStrength = ECKeyPairGenerator.FindECCurveByOid(((ECPublicBcpgKey)key).CurveOid).Curve.FieldSize;
}
}
}
@@ -146,6 +164,23 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
bcpgKey = new DsaPublicBcpgKey(dP.P, dP.Q, dP.G, dK.Y);
}
+ else if (pubKey is ECPublicKeyParameters)
+ {
+ ECPublicKeyParameters ecK = (ECPublicKeyParameters)pubKey;
+
+ if (algorithm == PublicKeyAlgorithmTag.ECDH)
+ {
+ bcpgKey = new ECDHPublicBcpgKey(ecK.PublicKeyParamSet, ecK.Q, HashAlgorithmTag.Sha256, SymmetricKeyAlgorithmTag.Aes128);
+ }
+ else if (algorithm == PublicKeyAlgorithmTag.ECDsa)
+ {
+ bcpgKey = new ECDsaPublicBcpgKey(ecK.PublicKeyParamSet, ecK.Q);
+ }
+ else
+ {
+ throw new PgpException("unknown EC algorithm");
+ }
+ }
else if (pubKey is ElGamalPublicKeyParameters)
{
ElGamalPublicKeyParameters eK = (ElGamalPublicKeyParameters) pubKey;
@@ -172,6 +207,11 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
}
}
+ public PgpPublicKey(PublicKeyPacket publicPk)
+ : this(publicPk, Platform.CreateArrayList(), Platform.CreateArrayList())
+ {
+ }
+
/// <summary>Constructor for a sub-key.</summary>
internal PgpPublicKey(
PublicKeyPacket publicPk,
@@ -426,14 +466,18 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
case PublicKeyAlgorithmTag.RsaEncrypt:
case PublicKeyAlgorithmTag.RsaGeneral:
case PublicKeyAlgorithmTag.RsaSign:
- RsaPublicBcpgKey rsaK = (RsaPublicBcpgKey) publicPk.Key;
+ RsaPublicBcpgKey rsaK = (RsaPublicBcpgKey)publicPk.Key;
return new RsaKeyParameters(false, rsaK.Modulus, rsaK.PublicExponent);
case PublicKeyAlgorithmTag.Dsa:
- DsaPublicBcpgKey dsaK = (DsaPublicBcpgKey) publicPk.Key;
+ DsaPublicBcpgKey dsaK = (DsaPublicBcpgKey)publicPk.Key;
return new DsaPublicKeyParameters(dsaK.Y, new DsaParameters(dsaK.P, dsaK.Q, dsaK.G));
+ case PublicKeyAlgorithmTag.ECDsa:
+ return GetECKey("ECDSA");
+ case PublicKeyAlgorithmTag.ECDH:
+ return GetECKey("ECDH");
case PublicKeyAlgorithmTag.ElGamalEncrypt:
case PublicKeyAlgorithmTag.ElGamalGeneral:
- ElGamalPublicBcpgKey elK = (ElGamalPublicBcpgKey) publicPk.Key;
+ ElGamalPublicBcpgKey elK = (ElGamalPublicBcpgKey)publicPk.Key;
return new ElGamalPublicKeyParameters(elK.Y, new ElGamalParameters(elK.P, elK.G));
default:
throw new PgpException("unknown public key algorithm encountered");
@@ -449,6 +493,14 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
}
}
+ private ECPublicKeyParameters GetECKey(string algorithm)
+ {
+ ECPublicBcpgKey ecK = (ECPublicBcpgKey)publicPk.Key;
+ X9ECParameters x9 = ECKeyPairGenerator.FindECCurveByOid(ecK.CurveOid);
+ ECPoint q = x9.Curve.DecodePoint(BigIntegers.AsUnsignedByteArray(ecK.EncodedPoint));
+ return new ECPublicKeyParameters(algorithm, q, ecK.CurveOid);
+ }
+
/// <summary>Allows enumeration of any user IDs associated with the key.</summary>
/// <returns>An <c>IEnumerable</c> of <c>string</c> objects.</returns>
public IEnumerable GetUserIds()
diff --git a/crypto/src/openpgp/PgpPublicKeyEncryptedData.cs b/crypto/src/openpgp/PgpPublicKeyEncryptedData.cs
index b6504cbcd..c2a351182 100644
--- a/crypto/src/openpgp/PgpPublicKeyEncryptedData.cs
+++ b/crypto/src/openpgp/PgpPublicKeyEncryptedData.cs
@@ -1,10 +1,13 @@
using System;
using System.IO;
+using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.IO;
@@ -77,22 +80,29 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
public SymmetricKeyAlgorithmTag GetSymmetricAlgorithm(
PgpPrivateKey privKey)
{
- byte[] plain = fetchSymmetricKeyData(privKey);
+ byte[] sessionData = RecoverSessionData(privKey);
- return (SymmetricKeyAlgorithmTag) plain[0];
+ return (SymmetricKeyAlgorithmTag)sessionData[0];
}
- /// <summary>Return the decrypted data stream for the packet.</summary>
+ /// <summary>Return the decrypted data stream for the packet.</summary>
public Stream GetDataStream(
PgpPrivateKey privKey)
{
- byte[] plain = fetchSymmetricKeyData(privKey);
+ byte[] sessionData = RecoverSessionData(privKey);
- IBufferedCipher c2;
- string cipherName = PgpUtilities.GetSymmetricCipherName((SymmetricKeyAlgorithmTag) plain[0]);
+ if (!ConfirmCheckSum(sessionData))
+ throw new PgpKeyValidationException("key checksum failed");
+
+ SymmetricKeyAlgorithmTag symmAlg = (SymmetricKeyAlgorithmTag)sessionData[0];
+ if (symmAlg == SymmetricKeyAlgorithmTag.Null)
+ return encData.GetInputStream();
+
+ IBufferedCipher cipher;
+ string cipherName = PgpUtilities.GetSymmetricCipherName(symmAlg);
string cName = cipherName;
- try
+ try
{
if (encData is SymmetricEncIntegrityPacket)
{
@@ -103,7 +113,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
cName += "/OpenPGPCFB/NoPadding";
}
- c2 = CipherUtilities.GetCipher(cName);
+ cipher = CipherUtilities.GetCipher(cName);
}
catch (PgpException e)
{
@@ -114,19 +124,16 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
throw new PgpException("exception creating cipher", e);
}
- if (c2 == null)
- return encData.GetInputStream();
-
- try
+ try
{
KeyParameter key = ParameterUtilities.CreateKeyParameter(
- cipherName, plain, 1, plain.Length - 3);
+ cipherName, sessionData, 1, sessionData.Length - 3);
- byte[] iv = new byte[c2.GetBlockSize()];
+ byte[] iv = new byte[cipher.GetBlockSize()];
- c2.Init(false, new ParametersWithIV(key, iv));
+ cipher.Init(false, new ParametersWithIV(key, iv));
- encStream = BcpgInputStream.Wrap(new CipherStream(encData.GetInputStream(), c2, null));
+ encStream = BcpgInputStream.Wrap(new CipherStream(encData.GetInputStream(), cipher, null));
if (encData is SymmetricEncIntegrityPacket)
{
@@ -178,75 +185,88 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
}
}
- private byte[] fetchSymmetricKeyData(
- PgpPrivateKey privKey)
+ private byte[] RecoverSessionData(PgpPrivateKey privKey)
{
- IBufferedCipher c1 = GetKeyCipher(keyData.Algorithm);
+ byte[][] secKeyData = keyData.GetEncSessionKey();
+
+ if (keyData.Algorithm == PublicKeyAlgorithmTag.ECDH)
+ {
+ ECDHPublicBcpgKey ecKey = (ECDHPublicBcpgKey)privKey.PublicKeyPacket.Key;
+ X9ECParameters x9Params = ECKeyPairGenerator.FindECCurveByOid(ecKey.CurveOid);
+
+ byte[] enc = secKeyData[0];
+
+ int pLen = ((((enc[0] & 0xff) << 8) + (enc[1] & 0xff)) + 7) / 8;
+ byte[] pEnc = new byte[pLen];
+
+ Array.Copy(enc, 2, pEnc, 0, pLen);
+
+ byte[] keyEnc = new byte[enc[pLen + 2]];
+
+ Array.Copy(enc, 2 + pLen + 1, keyEnc, 0, keyEnc.Length);
+
+ ECPoint publicPoint = x9Params.Curve.DecodePoint(pEnc);
+
+ ECPrivateKeyParameters privKeyParams = (ECPrivateKeyParameters)privKey.Key;
+ ECPoint S = publicPoint.Multiply(privKeyParams.D).Normalize();
+
+ KeyParameter key = new KeyParameter(Rfc6637Utilities.CreateKey(privKey.PublicKeyPacket, S));
+
+ IWrapper w = PgpUtilities.CreateWrapper(ecKey.SymmetricKeyAlgorithm);
+ w.Init(false, key);
- try
+ return PgpPad.UnpadSessionData(w.Unwrap(keyEnc, 0, keyEnc.Length));
+ }
+
+ IBufferedCipher cipher = GetKeyCipher(keyData.Algorithm);
+
+ try
{
- c1.Init(false, privKey.Key);
+ cipher.Init(false, privKey.Key);
}
catch (InvalidKeyException e)
{
throw new PgpException("error setting asymmetric cipher", e);
}
- BigInteger[] keyD = keyData.GetEncSessionKey();
-
- if (keyData.Algorithm == PublicKeyAlgorithmTag.RsaEncrypt
+ if (keyData.Algorithm == PublicKeyAlgorithmTag.RsaEncrypt
|| keyData.Algorithm == PublicKeyAlgorithmTag.RsaGeneral)
{
- c1.ProcessBytes(keyD[0].ToByteArrayUnsigned());
+ byte[] bi = secKeyData[0];
+
+ cipher.ProcessBytes(bi, 2, bi.Length - 2);
}
else
{
ElGamalPrivateKeyParameters k = (ElGamalPrivateKeyParameters)privKey.Key;
int size = (k.Parameters.P.BitLength + 7) / 8;
- byte[] bi = keyD[0].ToByteArray();
-
- int diff = bi.Length - size;
- if (diff >= 0)
- {
- c1.ProcessBytes(bi, diff, size);
- }
- else
- {
- byte[] zeros = new byte[-diff];
- c1.ProcessBytes(zeros);
- c1.ProcessBytes(bi);
- }
-
- bi = keyD[1].ToByteArray();
-
- diff = bi.Length - size;
- if (diff >= 0)
- {
- c1.ProcessBytes(bi, diff, size);
- }
- else
- {
- byte[] zeros = new byte[-diff];
- c1.ProcessBytes(zeros);
- c1.ProcessBytes(bi);
- }
+ ProcessEncodedMpi(cipher, size, secKeyData[0]);
+ ProcessEncodedMpi(cipher, size, secKeyData[1]);
}
- byte[] plain;
- try
+ try
{
- plain = c1.DoFinal();
+ return cipher.DoFinal();
}
catch (Exception e)
{
throw new PgpException("exception decrypting secret key", e);
}
-
- if (!ConfirmCheckSum(plain))
- throw new PgpKeyValidationException("key checksum failed");
-
- return plain;
}
+
+ private static void ProcessEncodedMpi(IBufferedCipher cipher, int size, byte[] mpiEnc)
+ {
+ if (mpiEnc.Length - 2 > size) // leading Zero? Shouldn't happen but...
+ {
+ cipher.ProcessBytes(mpiEnc, 3, mpiEnc.Length - 3);
+ }
+ else
+ {
+ byte[] tmp = new byte[size];
+ Array.Copy(mpiEnc, 2, tmp, tmp.Length - (mpiEnc.Length - 2), mpiEnc.Length - 2);
+ cipher.ProcessBytes(tmp, 0, tmp.Length);
+ }
+ }
}
}
diff --git a/crypto/src/openpgp/PgpSecretKey.cs b/crypto/src/openpgp/PgpSecretKey.cs
index 872316dd7..1027393ce 100644
--- a/crypto/src/openpgp/PgpSecretKey.cs
+++ b/crypto/src/openpgp/PgpSecretKey.cs
@@ -2,8 +2,11 @@ using System;
using System.Collections;
using System.IO;
+using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
@@ -59,6 +62,11 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
DsaPrivateKeyParameters dsK = (DsaPrivateKeyParameters) privKey.Key;
secKey = new DsaSecretBcpgKey(dsK.X);
break;
+ case PublicKeyAlgorithmTag.ECDH:
+ case PublicKeyAlgorithmTag.ECDsa:
+ ECPrivateKeyParameters ecK = (ECPrivateKeyParameters)privKey.Key;
+ secKey = new ECSecretBcpgKey(ecK.D);
+ break;
case PublicKeyAlgorithmTag.ElGamalEncrypt:
case PublicKeyAlgorithmTag.ElGamalGeneral:
ElGamalPrivateKeyParameters esK = (ElGamalPrivateKeyParameters) privKey.Key;
@@ -158,6 +166,21 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
{
}
+ public PgpSecretKey(
+ int certificationLevel,
+ PgpKeyPair keyPair,
+ string id,
+ SymmetricKeyAlgorithmTag encAlgorithm,
+ HashAlgorithmTag hashAlgorithm,
+ char[] passPhrase,
+ bool useSha1,
+ PgpSignatureSubpacketVector hashedPackets,
+ PgpSignatureSubpacketVector unhashedPackets,
+ SecureRandom rand)
+ : this(keyPair.PrivateKey, CertifiedPublicKey(certificationLevel, keyPair, id, hashedPackets, unhashedPackets, hashAlgorithm), encAlgorithm, passPhrase, useSha1, rand, true)
+ {
+ }
+
private static PgpPublicKey CertifiedPublicKey(
int certificationLevel,
PgpKeyPair keyPair,
@@ -194,6 +217,44 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
}
}
+
+ private static PgpPublicKey CertifiedPublicKey(
+ int certificationLevel,
+ PgpKeyPair keyPair,
+ string id,
+ PgpSignatureSubpacketVector hashedPackets,
+ PgpSignatureSubpacketVector unhashedPackets,
+ HashAlgorithmTag hashAlgorithm)
+ {
+ PgpSignatureGenerator sGen;
+ try
+ {
+ sGen = new PgpSignatureGenerator(keyPair.PublicKey.Algorithm, hashAlgorithm);
+ }
+ catch (Exception e)
+ {
+ throw new PgpException("Creating signature generator: " + e.Message, e);
+ }
+
+ //
+ // Generate the certification
+ //
+ sGen.InitSign(certificationLevel, keyPair.PrivateKey);
+
+ sGen.SetHashedSubpackets(hashedPackets);
+ sGen.SetUnhashedSubpackets(unhashedPackets);
+
+ try
+ {
+ PgpSignature certification = sGen.GenerateCertification(id, keyPair.PublicKey);
+ return PgpPublicKey.AddCertification(keyPair.PublicKey, id, certification);
+ }
+ catch (Exception e)
+ {
+ throw new PgpException("Exception doing certification: " + e.Message, e);
+ }
+ }
+
public PgpSecretKey(
int certificationLevel,
PublicKeyAlgorithmTag algorithm,
@@ -309,24 +370,13 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
private byte[] ExtractKeyData(
char[] passPhrase)
{
- SymmetricKeyAlgorithmTag alg = secret.EncAlgorithm;
+ SymmetricKeyAlgorithmTag encAlgorithm = secret.EncAlgorithm;
byte[] encData = secret.GetSecretKeyData();
- if (alg == SymmetricKeyAlgorithmTag.Null)
+ if (encAlgorithm == SymmetricKeyAlgorithmTag.Null)
// TODO Check checksum here?
return encData;
- IBufferedCipher c = null;
- try
- {
- string cName = PgpUtilities.GetSymmetricCipherName(alg);
- c = CipherUtilities.GetCipher(cName + "/CFB/NoPadding");
- }
- catch (Exception e)
- {
- throw new PgpException("Exception creating cipher", e);
- }
-
// TODO Factor this block out as 'decryptData'
try
{
@@ -336,9 +386,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
if (secret.PublicKeyPacket.Version >= 4)
{
- c.Init(false, new ParametersWithIV(key, iv));
-
- data = c.DoFinal(encData);
+ data = RecoverKeyData(encAlgorithm, "/CFB/NoPadding", key, iv, encData, 0, encData.Length);
bool useSha1 = secret.S2kUsage == SecretKeyPacket.UsageSha1;
byte[] check = Checksum(useSha1, data, (useSha1) ? data.Length - 20 : data.Length - 2);
@@ -364,15 +412,14 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
for (int i = 0; i != 4; i++)
{
- c.Init(false, new ParametersWithIV(key, iv));
-
int encLen = (((encData[pos] << 8) | (encData[pos + 1] & 0xff)) + 7) / 8;
data[pos] = encData[pos];
data[pos + 1] = encData[pos + 1];
pos += 2;
- c.DoFinal(encData, pos, encLen, data, pos);
+ byte[] tmp = RecoverKeyData(encAlgorithm, "/CFB/NoPadding", key, iv, encData, pos, encLen);
+ Array.Copy(tmp, 0, data, pos, encLen);
pos += encLen;
if (i != 3)
@@ -416,6 +463,25 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
}
}
+ private static byte[] RecoverKeyData(SymmetricKeyAlgorithmTag encAlgorithm, string modeAndPadding,
+ KeyParameter key, byte[] iv, byte[] keyData, int keyOff, int keyLen)
+ {
+ IBufferedCipher c;
+ try
+ {
+ string cName = PgpUtilities.GetSymmetricCipherName(encAlgorithm);
+ c = CipherUtilities.GetCipher(cName + modeAndPadding);
+ }
+ catch (Exception e)
+ {
+ throw new PgpException("Exception creating cipher", e);
+ }
+
+ c.Init(false, new ParametersWithIV(key, iv));
+
+ return c.DoFinal(keyData, keyOff, keyLen);
+ }
+
/// <summary>Extract a <c>PgpPrivateKey</c> from this secret key's encrypted contents.</summary>
public PgpPrivateKey ExtractPrivateKey(
char[] passPhrase)
@@ -453,6 +519,12 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
DsaParameters dsaParams = new DsaParameters(dsaPub.P, dsaPub.Q, dsaPub.G);
privateKey = new DsaPrivateKeyParameters(dsaPriv.X, dsaParams);
break;
+ case PublicKeyAlgorithmTag.ECDH:
+ privateKey = GetECKey("ECDH", bcpgIn);
+ break;
+ case PublicKeyAlgorithmTag.ECDsa:
+ privateKey = GetECKey("ECDSA", bcpgIn);
+ break;
case PublicKeyAlgorithmTag.ElGamalEncrypt:
case PublicKeyAlgorithmTag.ElGamalGeneral:
ElGamalPublicBcpgKey elPub = (ElGamalPublicBcpgKey)pubPk.Key;
@@ -464,7 +536,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
throw new PgpException("unknown public key algorithm encountered");
}
- return new PgpPrivateKey(privateKey, KeyId);
+ return new PgpPrivateKey(KeyId, pubPk, privateKey);
}
catch (PgpException e)
{
@@ -476,6 +548,13 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
}
}
+ private ECPrivateKeyParameters GetECKey(string algorithm, BcpgInputStream bcpgIn)
+ {
+ ECPublicBcpgKey ecdsaPub = (ECPublicBcpgKey)secret.PublicKeyPacket.Key;
+ ECSecretBcpgKey ecdsaPriv = new ECSecretBcpgKey(bcpgIn);
+ return new ECPrivateKeyParameters(algorithm, ecdsaPriv.X, ecdsaPub.CurveOid);
+ }
+
private static byte[] Checksum(
bool useSha1,
byte[] bytes,
@@ -585,6 +664,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
SymmetricKeyAlgorithmTag newEncAlgorithm,
SecureRandom rand)
{
+
if (key.IsPrivateKeyEmpty)
throw new PgpException("no private key in this SecretKey - public key present only.");
@@ -698,5 +778,174 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
return c.DoFinal(rawKeyData);
}
+
+ /**
+ * Parse a secret key from one of the GPG S expression keys associating it with the passed in public key.
+ *
+ * @return a secret key object.
+ */
+ public static PgpSecretKey ParseSecretKeyFromSExpr(Stream inputStream, char[] passPhrase, PgpPublicKey pubKey)
+ {
+ SXprUtilities.SkipOpenParenthesis(inputStream);
+
+ string type = SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
+ if (type.Equals("protected-private-key"))
+ {
+ SXprUtilities.SkipOpenParenthesis(inputStream);
+
+ string curveName;
+
+ string keyType = SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
+ if (keyType.Equals("ecc"))
+ {
+ SXprUtilities.SkipOpenParenthesis(inputStream);
+
+ string curveID = SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
+ curveName = SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
+
+ SXprUtilities.SkipCloseParenthesis(inputStream);
+ }
+ else
+ {
+ throw new PgpException("no curve details found");
+ }
+
+ byte[] qVal;
+
+ SXprUtilities.SkipOpenParenthesis(inputStream);
+
+ type = SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
+ if (type.Equals("q"))
+ {
+ qVal = SXprUtilities.ReadBytes(inputStream, inputStream.ReadByte());
+ }
+ else
+ {
+ throw new PgpException("no q value found");
+ }
+
+ SXprUtilities.SkipCloseParenthesis(inputStream);
+
+ byte[] dValue = GetDValue(inputStream, passPhrase, curveName);
+ // TODO: check SHA-1 hash.
+
+ return new PgpSecretKey(new SecretKeyPacket(pubKey.PublicKeyPacket, SymmetricKeyAlgorithmTag.Null, null, null,
+ new ECSecretBcpgKey(new BigInteger(1, dValue)).GetEncoded()), pubKey);
+ }
+
+ throw new PgpException("unknown key type found");
+ }
+
+ /**
+ * Parse a secret key from one of the GPG S expression keys.
+ *
+ * @return a secret key object.
+ */
+ public static PgpSecretKey ParseSecretKeyFromSExpr(Stream inputStream, char[] passPhrase)
+ {
+ SXprUtilities.SkipOpenParenthesis(inputStream);
+
+ string type = SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
+ if (type.Equals("protected-private-key"))
+ {
+ SXprUtilities.SkipOpenParenthesis(inputStream);
+
+ string curveName;
+
+ string keyType = SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
+ if (keyType.Equals("ecc"))
+ {
+ SXprUtilities.SkipOpenParenthesis(inputStream);
+
+ string curveID = SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
+ curveName = SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
+
+ if (curveName.StartsWith("NIST "))
+ {
+ curveName = curveName.Substring("NIST ".Length);
+ }
+
+ SXprUtilities.SkipCloseParenthesis(inputStream);
+ }
+ else
+ {
+ throw new PgpException("no curve details found");
+ }
+
+ byte[] qVal;
+
+ SXprUtilities.SkipOpenParenthesis(inputStream);
+
+ type = SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
+ if (type.Equals("q"))
+ {
+ qVal = SXprUtilities.ReadBytes(inputStream, inputStream.ReadByte());
+ }
+ else
+ {
+ throw new PgpException("no q value found");
+ }
+
+ PublicKeyPacket pubPacket = new PublicKeyPacket(PublicKeyAlgorithmTag.ECDsa, DateTime.UtcNow,
+ new ECDsaPublicBcpgKey(ECNamedCurveTable.GetOid(curveName), new BigInteger(1, qVal)));
+
+ SXprUtilities.SkipCloseParenthesis(inputStream);
+
+ byte[] dValue = GetDValue(inputStream, passPhrase, curveName);
+ // TODO: check SHA-1 hash.
+
+ return new PgpSecretKey(new SecretKeyPacket(pubPacket, SymmetricKeyAlgorithmTag.Null, null, null,
+ new ECSecretBcpgKey(new BigInteger(1, dValue)).GetEncoded()), new PgpPublicKey(pubPacket));
+ }
+
+ throw new PgpException("unknown key type found");
+ }
+
+ private static byte[] GetDValue(Stream inputStream, char[] passPhrase, string curveName)
+ {
+ string type;
+ SXprUtilities.SkipOpenParenthesis(inputStream);
+
+ string protection;
+ S2k s2k;
+ byte[] iv;
+ byte[] secKeyData;
+
+ type = SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
+ if (type.Equals("protected"))
+ {
+ protection = SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
+
+ SXprUtilities.SkipOpenParenthesis(inputStream);
+
+ s2k = SXprUtilities.ParseS2k(inputStream);
+
+ iv = SXprUtilities.ReadBytes(inputStream, inputStream.ReadByte());
+
+ SXprUtilities.SkipCloseParenthesis(inputStream);
+
+ secKeyData = SXprUtilities.ReadBytes(inputStream, inputStream.ReadByte());
+ }
+ else
+ {
+ throw new PgpException("protected block not found");
+ }
+
+ // TODO: recognise other algorithms
+ KeyParameter key = PgpUtilities.MakeKeyFromPassPhrase(SymmetricKeyAlgorithmTag.Aes128, s2k, passPhrase);
+
+ byte[] data = RecoverKeyData(SymmetricKeyAlgorithmTag.Aes128, "/CBC/NoPadding", key, iv, secKeyData, 0, secKeyData.Length);
+
+ //
+ // parse the secret key S-expr
+ //
+ Stream keyIn = new MemoryStream(data, false);
+
+ SXprUtilities.SkipOpenParenthesis(keyIn);
+ SXprUtilities.SkipOpenParenthesis(keyIn);
+ SXprUtilities.SkipOpenParenthesis(keyIn);
+ String name = SXprUtilities.ReadString(keyIn, keyIn.ReadByte());
+ return SXprUtilities.ReadBytes(keyIn, keyIn.ReadByte());
+ }
}
}
diff --git a/crypto/src/openpgp/PgpSignatureSubpacketGenerator.cs b/crypto/src/openpgp/PgpSignatureSubpacketGenerator.cs
index 4adf64012..d2177d09c 100644
--- a/crypto/src/openpgp/PgpSignatureSubpacketGenerator.cs
+++ b/crypto/src/openpgp/PgpSignatureSubpacketGenerator.cs
@@ -25,7 +25,14 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
list.Add(new Exportable(isCritical, isExportable));
}
- /// <summary>
+ public void SetFeature(
+ bool isCritical,
+ byte feature)
+ {
+ list.Add(new Features(isCritical, feature));
+ }
+
+ /// <summary>
/// Add a TrustSignature packet to the signature. The values for depth and trust are largely
/// installation dependent but there are some guidelines in RFC 4880 - 5.2.3.13.
/// </summary>
@@ -117,7 +124,17 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
list.Add(new SignerUserId(isCritical, userId));
}
- public void SetEmbeddedSignature(
+ public void SetSignerUserId(
+ bool isCritical,
+ byte[] rawUserId)
+ {
+ if (rawUserId == null)
+ throw new ArgumentNullException("rawUserId");
+
+ list.Add(new SignerUserId(isCritical, false, rawUserId));
+ }
+
+ public void SetEmbeddedSignature(
bool isCritical,
PgpSignature pgpSignature)
{
@@ -136,7 +153,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
Array.Copy(sig, sig.Length - data.Length, data, 0, data.Length);
- list.Add(new EmbeddedSignature(isCritical, data));
+ list.Add(new EmbeddedSignature(isCritical, false, data));
}
public void SetPrimaryUserId(
diff --git a/crypto/src/openpgp/PgpSignatureSubpacketVector.cs b/crypto/src/openpgp/PgpSignatureSubpacketVector.cs
index 68fe4b594..156243f4e 100644
--- a/crypto/src/openpgp/PgpSignatureSubpacketVector.cs
+++ b/crypto/src/openpgp/PgpSignatureSubpacketVector.cs
@@ -209,7 +209,17 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
return list;
}
- [Obsolete("Use 'Count' property instead")]
+ public Features GetFeatures()
+ {
+ SignatureSubpacket p = this.GetSubpacket(SignatureSubpacketTag.Features);
+
+ if (p == null)
+ return null;
+
+ return new Features(p.IsCritical(), p.IsLongLength(), p.GetData());
+ }
+
+ [Obsolete("Use 'Count' property instead")]
public int Size
{
get { return packets.Length; }
diff --git a/crypto/src/openpgp/PgpUtilities.cs b/crypto/src/openpgp/PgpUtilities.cs
index 32e37b819..e4551db07 100644
--- a/crypto/src/openpgp/PgpUtilities.cs
+++ b/crypto/src/openpgp/PgpUtilities.cs
@@ -86,7 +86,13 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
case PublicKeyAlgorithmTag.Dsa:
encAlg = "DSA";
break;
- case PublicKeyAlgorithmTag.ElGamalEncrypt: // in some malformed cases.
+ case PublicKeyAlgorithmTag.ECDH:
+ encAlg = "ECDH";
+ break;
+ case PublicKeyAlgorithmTag.ECDsa:
+ encAlg = "ECDSA";
+ break;
+ case PublicKeyAlgorithmTag.ElGamalEncrypt: // in some malformed cases.
case PublicKeyAlgorithmTag.ElGamalGeneral:
encAlg = "ElGamal";
break;
@@ -135,7 +141,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
}
}
- public static int GetKeySize(SymmetricKeyAlgorithmTag algorithm)
+ public static int GetKeySize(SymmetricKeyAlgorithmTag algorithm)
{
int keySize;
switch (algorithm)
@@ -193,7 +199,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
char[] passPhrase)
{
int keySize = GetKeySize(algorithm);
- byte[] pBytes = Strings.ToByteArray(new string(passPhrase));
+ byte[] pBytes = Encoding.UTF8.GetBytes(passPhrase);
byte[] keyBytes = new byte[(keySize + 7) / 8];
int generatedBytes = 0;
@@ -431,5 +437,22 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
return new ArmoredInputStream(inputStream, hasHeaders);
}
}
+
+ internal static IWrapper CreateWrapper(SymmetricKeyAlgorithmTag encAlgorithm)
+ {
+ switch (encAlgorithm)
+ {
+ case SymmetricKeyAlgorithmTag.Aes128:
+ case SymmetricKeyAlgorithmTag.Aes192:
+ case SymmetricKeyAlgorithmTag.Aes256:
+ return WrapperUtilities.GetWrapper("AESWRAP");
+ case SymmetricKeyAlgorithmTag.Camellia128:
+ case SymmetricKeyAlgorithmTag.Camellia192:
+ case SymmetricKeyAlgorithmTag.Camellia256:
+ return WrapperUtilities.GetWrapper("CAMELLIAWRAP");
+ default:
+ throw new PgpException("unknown wrap algorithm: " + encAlgorithm);
+ }
+ }
}
}
diff --git a/crypto/src/openpgp/Rfc6637Utilities.cs b/crypto/src/openpgp/Rfc6637Utilities.cs
new file mode 100644
index 000000000..5d992ec51
--- /dev/null
+++ b/crypto/src/openpgp/Rfc6637Utilities.cs
@@ -0,0 +1,138 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+ public sealed class Rfc6637Utilities
+ {
+ private Rfc6637Utilities()
+ {
+ }
+
+ // "Anonymous Sender ", which is the octet sequence
+ private static readonly byte[] ANONYMOUS_SENDER = Hex.Decode("416E6F6E796D6F75732053656E64657220202020");
+
+ public static string GetAgreementAlgorithm(PublicKeyPacket pubKeyData)
+ {
+ ECDHPublicBcpgKey ecKey = (ECDHPublicBcpgKey)pubKeyData.Key;
+
+ switch (ecKey.HashAlgorithm)
+ {
+ case HashAlgorithmTag.Sha256:
+ return "ECCDHwithSHA256CKDF";
+ case HashAlgorithmTag.Sha384:
+ return "ECCDHwithSHA384CKDF";
+ case HashAlgorithmTag.Sha512:
+ return "ECCDHwithSHA512CKDF";
+ default:
+ throw new ArgumentException("Unknown hash algorithm specified: " + ecKey.HashAlgorithm);
+ }
+ }
+
+ public static DerObjectIdentifier GetKeyEncryptionOID(SymmetricKeyAlgorithmTag algID)
+ {
+ switch (algID)
+ {
+ case SymmetricKeyAlgorithmTag.Aes128:
+ return NistObjectIdentifiers.IdAes128Wrap;
+ case SymmetricKeyAlgorithmTag.Aes192:
+ return NistObjectIdentifiers.IdAes192Wrap;
+ case SymmetricKeyAlgorithmTag.Aes256:
+ return NistObjectIdentifiers.IdAes256Wrap;
+ default:
+ throw new PgpException("unknown symmetric algorithm ID: " + algID);
+ }
+ }
+
+ public static int GetKeyLength(SymmetricKeyAlgorithmTag algID)
+ {
+ switch (algID)
+ {
+ case SymmetricKeyAlgorithmTag.Aes128:
+ return 16;
+ case SymmetricKeyAlgorithmTag.Aes192:
+ return 24;
+ case SymmetricKeyAlgorithmTag.Aes256:
+ return 32;
+ default:
+ throw new PgpException("unknown symmetric algorithm ID: " + algID);
+ }
+ }
+
+ public static byte[] CreateKey(PublicKeyPacket pubKeyData, ECPoint s)
+ {
+ byte[] userKeyingMaterial = CreateUserKeyingMaterial(pubKeyData);
+
+ ECDHPublicBcpgKey ecKey = (ECDHPublicBcpgKey)pubKeyData.Key;
+
+ return Kdf(ecKey.HashAlgorithm, s, GetKeyLength(ecKey.SymmetricKeyAlgorithm), userKeyingMaterial);
+ }
+
+ // RFC 6637 - Section 8
+ // curve_OID_len = (byte)len(curve_OID);
+ // Param = curve_OID_len || curve_OID || public_key_alg_ID || 03
+ // || 01 || KDF_hash_ID || KEK_alg_ID for AESKeyWrap || "Anonymous
+ // Sender " || recipient_fingerprint;
+ // Z_len = the key size for the KEK_alg_ID used with AESKeyWrap
+ // Compute Z = KDF( S, Z_len, Param );
+ public static byte[] CreateUserKeyingMaterial(PublicKeyPacket pubKeyData)
+ {
+ MemoryStream pOut = new MemoryStream();
+ ECDHPublicBcpgKey ecKey = (ECDHPublicBcpgKey)pubKeyData.Key;
+ byte[] encOid = ecKey.CurveOid.GetEncoded();
+
+ pOut.Write(encOid, 1, encOid.Length - 1);
+ pOut.WriteByte((byte)pubKeyData.Algorithm);
+ pOut.WriteByte(0x03);
+ pOut.WriteByte(0x01);
+ pOut.WriteByte((byte)ecKey.HashAlgorithm);
+ pOut.WriteByte((byte)ecKey.SymmetricKeyAlgorithm);
+ pOut.Write(ANONYMOUS_SENDER, 0, ANONYMOUS_SENDER.Length);
+
+ byte[] fingerprint = PgpPublicKey.CalculateFingerprint(pubKeyData);
+ pOut.Write(fingerprint, 0, fingerprint.Length);
+
+ return pOut.ToArray();
+ }
+
+ // RFC 6637 - Section 7
+ // Implements KDF( X, oBits, Param );
+ // Input: point X = (x,y)
+ // oBits - the desired size of output
+ // hBits - the size of output of hash function Hash
+ // Param - octets representing the parameters
+ // Assumes that oBits <= hBits
+ // Convert the point X to the octet string, see section 6:
+ // ZB' = 04 || x || y
+ // and extract the x portion from ZB'
+ // ZB = x;
+ // MB = Hash ( 00 || 00 || 00 || 01 || ZB || Param );
+ // return oBits leftmost bits of MB.
+ private static byte[] Kdf(HashAlgorithmTag digestAlg, ECPoint s, int keyLen, byte[] parameters)
+ {
+ byte[] ZB = s.XCoord.GetEncoded();
+
+ string digestName = PgpUtilities.GetDigestName(digestAlg);
+ IDigest digest = DigestUtilities.GetDigest(digestName);
+
+ digest.Update(0x00);
+ digest.Update(0x00);
+ digest.Update(0x00);
+ digest.Update(0x01);
+ digest.BlockUpdate(ZB, 0, ZB.Length);
+ digest.BlockUpdate(parameters, 0, parameters.Length);
+
+ byte[] hash = DigestUtilities.DoFinal(digest);
+
+ return Arrays.CopyOfRange(hash, 0, keyLen);
+ }
+ }
+}
diff --git a/crypto/src/openpgp/SXprUtilities.cs b/crypto/src/openpgp/SXprUtilities.cs
new file mode 100644
index 000000000..68ff373a8
--- /dev/null
+++ b/crypto/src/openpgp/SXprUtilities.cs
@@ -0,0 +1,102 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+ /**
+ * Utility functions for looking a S-expression keys. This class will move when it finds a better home!
+ * <p>
+ * Format documented here:
+ * http://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=agent/keyformat.txt;h=42c4b1f06faf1bbe71ffadc2fee0fad6bec91a97;hb=refs/heads/master
+ * </p>
+ */
+ public sealed class SXprUtilities
+ {
+ private SXprUtilities()
+ {
+ }
+
+ private static int ReadLength(Stream input, int ch)
+ {
+ int len = ch - '0';
+
+ while ((ch = input.ReadByte()) >= 0 && ch != ':')
+ {
+ len = len * 10 + ch - '0';
+ }
+
+ return len;
+ }
+
+ internal static string ReadString(Stream input, int ch)
+ {
+ int len = ReadLength(input, ch);
+
+ char[] chars = new char[len];
+
+ for (int i = 0; i != chars.Length; i++)
+ {
+ chars[i] = (char)input.ReadByte();
+ }
+
+ return new string(chars);
+ }
+
+ internal static byte[] ReadBytes(Stream input, int ch)
+ {
+ int len = ReadLength(input, ch);
+
+ byte[] data = new byte[len];
+
+ Streams.ReadFully(input, data);
+
+ return data;
+ }
+
+ internal static S2k ParseS2k(Stream input)
+ {
+ SkipOpenParenthesis(input);
+
+ string alg = ReadString(input, input.ReadByte());
+ byte[] iv = ReadBytes(input, input.ReadByte());
+ long iterationCount = Int64.Parse(ReadString(input, input.ReadByte()));
+
+ SkipCloseParenthesis(input);
+
+ // we have to return the actual iteration count provided.
+ return new MyS2k(HashAlgorithmTag.Sha1, iv, iterationCount);
+ }
+
+ internal static void SkipOpenParenthesis(Stream input)
+ {
+ int ch = input.ReadByte();
+ if (ch != '(')
+ throw new IOException("unknown character encountered");
+ }
+
+ internal static void SkipCloseParenthesis(Stream input)
+ {
+ int ch = input.ReadByte();
+ if (ch != ')')
+ throw new IOException("unknown character encountered");
+ }
+
+ private class MyS2k : S2k
+ {
+ private readonly long mIterationCount64;
+
+ internal MyS2k(HashAlgorithmTag algorithm, byte[] iv, long iterationCount64)
+ : base(algorithm, iv, (int)iterationCount64)
+ {
+ this.mIterationCount64 = iterationCount64;
+ }
+
+ public override long IterationCount
+ {
+ get { return mIterationCount64; }
+ }
+ }
+ }
+}
diff --git a/crypto/src/openpgp/WrappedGeneratorStream.cs b/crypto/src/openpgp/WrappedGeneratorStream.cs
index 6fc7329af..cdc9befb3 100644
--- a/crypto/src/openpgp/WrappedGeneratorStream.cs
+++ b/crypto/src/openpgp/WrappedGeneratorStream.cs
@@ -1,6 +1,6 @@
using System.IO;
-using Org.BouncyCastle.Asn1.Utilities;
+using Org.BouncyCastle.Utilities.IO;
namespace Org.BouncyCastle.Bcpg.OpenPgp
{
diff --git a/crypto/src/openssl/PEMReader.cs b/crypto/src/openssl/PEMReader.cs
index 8c19fe601..ec5d1b414 100644
--- a/crypto/src/openssl/PEMReader.cs
+++ b/crypto/src/openssl/PEMReader.cs
@@ -109,6 +109,7 @@ namespace Org.BouncyCastle.OpenSsl
case "X509 CERTIFICATE":
return ReadCertificate(obj);
case "PKCS7":
+ case "CMS":
return ReadPkcs7(obj);
case "X509 CRL":
return ReadCrl(obj);
diff --git a/crypto/src/pkcs/Pkcs10CertificationRequest.cs b/crypto/src/pkcs/Pkcs10CertificationRequest.cs
index 9f24eb18a..b68979cad 100644
--- a/crypto/src/pkcs/Pkcs10CertificationRequest.cs
+++ b/crypto/src/pkcs/Pkcs10CertificationRequest.cs
@@ -15,6 +15,7 @@ using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Collections;
using Org.BouncyCastle.X509;
+using Org.BouncyCastle.Crypto.Operators;
namespace Org.BouncyCastle.Pkcs
{
@@ -198,17 +199,18 @@ namespace Org.BouncyCastle.Pkcs
Stream input)
: base((Asn1Sequence) Asn1Object.FromStream(input))
{
- }
-
- /// <summary>
- /// Instantiate a Pkcs10CertificationRequest object with the necessary credentials.
- /// </summary>
- ///<param name="signatureAlgorithm">Name of Sig Alg.</param>
- /// <param name="subject">X509Name of subject eg OU="My unit." O="My Organisatioin" C="au" </param>
- /// <param name="publicKey">Public Key to be included in cert reqest.</param>
- /// <param name="attributes">ASN1Set of Attributes.</param>
- /// <param name="signingKey">Matching Private key for nominated (above) public key to be used to sign the request.</param>
- public Pkcs10CertificationRequest(
+ }
+
+ /// <summary>
+ /// Instantiate a Pkcs10CertificationRequest object with the necessary credentials.
+ /// </summary>
+ ///<param name="signatureAlgorithm">Name of Sig Alg.</param>
+ /// <param name="subject">X509Name of subject eg OU="My unit." O="My Organisatioin" C="au" </param>
+ /// <param name="publicKey">Public Key to be included in cert reqest.</param>
+ /// <param name="attributes">ASN1Set of Attributes.</param>
+ /// <param name="signingKey">Matching Private key for nominated (above) public key to be used to sign the request.</param>
+ [Obsolete("Use constructor with an ISignatureCalculator")]
+ public Pkcs10CertificationRequest(
string signatureAlgorithm,
X509Name subject,
AsymmetricKeyParameter publicKey,
@@ -226,79 +228,84 @@ namespace Org.BouncyCastle.Pkcs
if (!signingKey.IsPrivate)
throw new ArgumentException("key for signing must be private", "signingKey");
-// DerObjectIdentifier sigOid = SignerUtilities.GetObjectIdentifier(signatureAlgorithm);
- string algorithmName = Platform.ToUpperInvariant(signatureAlgorithm);
- DerObjectIdentifier sigOid = (DerObjectIdentifier) algorithms[algorithmName];
-
- if (sigOid == null)
- {
- try
- {
- sigOid = new DerObjectIdentifier(algorithmName);
- }
- catch (Exception e)
- {
- throw new ArgumentException("Unknown signature type requested", e);
- }
- }
-
- if (noParams.Contains(sigOid))
- {
- this.sigAlgId = new AlgorithmIdentifier(sigOid);
- }
- else if (exParams.Contains(algorithmName))
- {
- this.sigAlgId = new AlgorithmIdentifier(sigOid, (Asn1Encodable) exParams[algorithmName]);
- }
- else
- {
- this.sigAlgId = new AlgorithmIdentifier(sigOid, DerNull.Instance);
- }
-
- SubjectPublicKeyInfo pubInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey);
-
- this.reqInfo = new CertificationRequestInfo(subject, pubInfo, attributes);
-
- ISigner sig = SignerUtilities.GetSigner(signatureAlgorithm);
-
- sig.Init(true, signingKey);
-
- try
- {
- // Encode.
- byte[] b = reqInfo.GetDerEncoded();
- sig.BlockUpdate(b, 0, b.Length);
- }
- catch (Exception e)
- {
- throw new ArgumentException("exception encoding TBS cert request", e);
- }
-
- // Generate Signature.
- sigBits = new DerBitString(sig.GenerateSignature());
+ init(new Asn1SignatureCalculator(signatureAlgorithm, signingKey), subject, publicKey, attributes, signingKey);
}
-// internal Pkcs10CertificationRequest(
-// Asn1InputStream seqStream)
-// {
-// Asn1Sequence seq = (Asn1Sequence) seqStream.ReadObject();
-// try
-// {
-// this.reqInfo = CertificationRequestInfo.GetInstance(seq[0]);
-// this.sigAlgId = AlgorithmIdentifier.GetInstance(seq[1]);
-// this.sigBits = (DerBitString) seq[2];
-// }
-// catch (Exception ex)
-// {
-// throw new ArgumentException("Create From Asn1Sequence: " + ex.Message);
-// }
-// }
-
- /// <summary>
- /// Get the public key.
- /// </summary>
- /// <returns>The public key.</returns>
- public AsymmetricKeyParameter GetPublicKey()
+ /// <summary>
+ /// Instantiate a Pkcs10CertificationRequest object with the necessary credentials.
+ /// </summary>
+ ///<param name="signatureCalculator">The signature calculator to sign the PKCS#10 request with.</param>
+ /// <param name="subject">X509Name of subject eg OU="My unit." O="My Organisatioin" C="au" </param>
+ /// <param name="publicKey">Public Key to be included in cert reqest.</param>
+ /// <param name="attributes">ASN1Set of Attributes.</param>
+ /// <param name="signingKey">Matching Private key for nominated (above) public key to be used to sign the request.</param>
+ public Pkcs10CertificationRequest(
+ ISignatureCalculator signatureCalculator,
+ X509Name subject,
+ AsymmetricKeyParameter publicKey,
+ Asn1Set attributes,
+ AsymmetricKeyParameter signingKey)
+ {
+ if (signatureCalculator == null)
+ throw new ArgumentNullException("signatureCalculator");
+ if (subject == null)
+ throw new ArgumentNullException("subject");
+ if (publicKey == null)
+ throw new ArgumentNullException("publicKey");
+ if (publicKey.IsPrivate)
+ throw new ArgumentException("expected public key", "publicKey");
+ if (!signingKey.IsPrivate)
+ throw new ArgumentException("key for signing must be private", "signingKey");
+
+ init(signatureCalculator, subject, publicKey, attributes, signingKey);
+ }
+
+ private void init(
+ ISignatureCalculator signatureCalculator,
+ X509Name subject,
+ AsymmetricKeyParameter publicKey,
+ Asn1Set attributes,
+ AsymmetricKeyParameter signingKey)
+ {
+ this.sigAlgId = (AlgorithmIdentifier)signatureCalculator.AlgorithmDetails;
+
+ SubjectPublicKeyInfo pubInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey);
+
+ this.reqInfo = new CertificationRequestInfo(subject, pubInfo, attributes);
+
+ IStreamCalculator streamCalculator = signatureCalculator.CreateCalculator();
+
+ byte[] reqInfoData = reqInfo.GetDerEncoded();
+
+ streamCalculator.Stream.Write(reqInfoData, 0, reqInfoData.Length);
+
+ streamCalculator.Stream.Close();
+
+ // Generate Signature.
+ sigBits = new DerBitString(((IBlockResult)streamCalculator.GetResult()).DoFinal());
+ }
+
+ // internal Pkcs10CertificationRequest(
+ // Asn1InputStream seqStream)
+ // {
+ // Asn1Sequence seq = (Asn1Sequence) seqStream.ReadObject();
+ // try
+ // {
+ // this.reqInfo = CertificationRequestInfo.GetInstance(seq[0]);
+ // this.sigAlgId = AlgorithmIdentifier.GetInstance(seq[1]);
+ // this.sigBits = (DerBitString) seq[2];
+ // }
+ // catch (Exception ex)
+ // {
+ // throw new ArgumentException("Create From Asn1Sequence: " + ex.Message);
+ // }
+ // }
+
+ /// <summary>
+ /// Get the public key.
+ /// </summary>
+ /// <returns>The public key.</returns>
+ public AsymmetricKeyParameter GetPublicKey()
{
return PublicKeyFactory.CreateKey(reqInfo.SubjectPublicKeyInfo);
}
@@ -315,55 +322,47 @@ namespace Org.BouncyCastle.Pkcs
public bool Verify(
AsymmetricKeyParameter publicKey)
{
- ISigner sig;
-
- try
- {
- sig = SignerUtilities.GetSigner(GetSignatureName(sigAlgId));
- }
- catch (Exception e)
- {
- // try an alternate
- string alt = (string) oids[sigAlgId.ObjectID];
-
- if (alt != null)
- {
- sig = SignerUtilities.GetSigner(alt);
- }
- else
- {
- throw e;
- }
- }
-
- SetSignatureParameters(sig, sigAlgId.Parameters);
-
- sig.Init(false, publicKey);
-
- try
- {
- byte[] b = reqInfo.GetDerEncoded();
- sig.BlockUpdate(b, 0, b.Length);
- }
- catch (Exception e)
- {
- throw new SignatureException("exception encoding TBS cert request", e);
- }
-
- return sig.VerifySignature(sigBits.GetBytes());
+ return Verify(new Asn1SignatureVerifierProvider(publicKey));
}
-// /// <summary>
-// /// Get the Der Encoded Pkcs10 Certification Request.
-// /// </summary>
-// /// <returns>A byte array.</returns>
-// public byte[] GetEncoded()
-// {
-// return new CertificationRequest(reqInfo, sigAlgId, sigBits).GetDerEncoded();
-// }
-
- // TODO Figure out how to set parameters on an ISigner
- private void SetSignatureParameters(
+ public bool Verify(
+ ISignatureVerifierProvider verifierProvider)
+ {
+ return Verify(verifierProvider.CreateSignatureVerifier(sigAlgId));
+ }
+
+ public bool Verify(
+ ISignatureVerifier verifier)
+ {
+ try
+ {
+ byte[] b = reqInfo.GetDerEncoded();
+
+ IStreamCalculator streamCalculator = verifier.CreateCalculator();
+
+ streamCalculator.Stream.Write(b, 0, b.Length);
+
+ streamCalculator.Stream.Close();
+
+ return ((IVerifier)streamCalculator.GetResult()).IsVerified(sigBits.GetBytes());
+ }
+ catch (Exception e)
+ {
+ throw new SignatureException("exception encoding TBS cert request", e);
+ }
+ }
+
+ // /// <summary>
+ // /// Get the Der Encoded Pkcs10 Certification Request.
+ // /// </summary>
+ // /// <returns>A byte array.</returns>
+ // public byte[] GetEncoded()
+ // {
+ // return new CertificationRequest(reqInfo, sigAlgId, sigBits).GetDerEncoded();
+ // }
+
+ // TODO Figure out how to set parameters on an ISigner
+ private void SetSignatureParameters(
ISigner signature,
Asn1Encodable asn1Params)
{
diff --git a/crypto/src/security/AgreementUtilities.cs b/crypto/src/security/AgreementUtilities.cs
index 4c61ac354..12d427c8c 100644
--- a/crypto/src/security/AgreementUtilities.cs
+++ b/crypto/src/security/AgreementUtilities.cs
@@ -22,14 +22,14 @@ namespace Org.BouncyCastle.Security
private static readonly IDictionary algorithms = Platform.CreateHashtable();
//private static readonly IDictionary oids = Platform.CreateHashtable();
- static AgreementUtilities()
+ static AgreementUtilities()
{
- //algorithms[X9ObjectIdentifiers.DHSinglePassCofactorDHSha1KdfScheme.Id] = ?;
+ algorithms[X9ObjectIdentifiers.DHSinglePassCofactorDHSha1KdfScheme.Id] = "ECCDHWITHSHA1KDF";
algorithms[X9ObjectIdentifiers.DHSinglePassStdDHSha1KdfScheme.Id] = "ECDHWITHSHA1KDF";
algorithms[X9ObjectIdentifiers.MqvSinglePassSha1KdfScheme.Id] = "ECMQVWITHSHA1KDF";
}
- public static IBasicAgreement GetBasicAgreement(
+ public static IBasicAgreement GetBasicAgreement(
DerObjectIdentifier oid)
{
return GetBasicAgreement(oid.Id);
@@ -52,8 +52,8 @@ namespace Org.BouncyCastle.Security
if (mechanism == "ECDH")
return new ECDHBasicAgreement();
- if (mechanism == "ECDHC")
- return new ECDHCBasicAgreement();
+ if (mechanism == "ECDHC" || mechanism == "ECCDH")
+ return new ECDHCBasicAgreement();
if (mechanism == "ECMQV")
return new ECMqvBasicAgreement();
diff --git a/crypto/src/security/SecureRandom.cs b/crypto/src/security/SecureRandom.cs
index f46427a5c..137a471c1 100644
--- a/crypto/src/security/SecureRandom.cs
+++ b/crypto/src/security/SecureRandom.cs
@@ -13,12 +13,16 @@ namespace Org.BouncyCastle.Security
{
private static long counter = Times.NanoTime();
+#if NETCF_1_0
+ private static object counterLock = new object();
private static long NextCounterValue()
{
- return Interlocked.Increment(ref counter);
+ lock (counterLock)
+ {
+ return ++counter;
+ }
}
-#if NETCF_1_0
private static readonly SecureRandom[] master = { null };
private static SecureRandom Master
{
@@ -43,6 +47,11 @@ namespace Org.BouncyCastle.Security
}
}
#else
+ private static long NextCounterValue()
+ {
+ return Interlocked.Increment(ref counter);
+ }
+
private static readonly SecureRandom master = new SecureRandom(new CryptoApiRandomGenerator());
private static SecureRandom Master
{
diff --git a/crypto/src/util/io/FilterStream.cs b/crypto/src/util/io/FilterStream.cs
new file mode 100644
index 000000000..260ce1789
--- /dev/null
+++ b/crypto/src/util/io/FilterStream.cs
@@ -0,0 +1,66 @@
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.IO
+{
+ public class FilterStream : Stream
+ {
+ public FilterStream(Stream s)
+ {
+ this.s = s;
+ }
+ public override bool CanRead
+ {
+ get { return s.CanRead; }
+ }
+ public override bool CanSeek
+ {
+ get { return s.CanSeek; }
+ }
+ public override bool CanWrite
+ {
+ get { return s.CanWrite; }
+ }
+ public override long Length
+ {
+ get { return s.Length; }
+ }
+ public override long Position
+ {
+ get { return s.Position; }
+ set { s.Position = value; }
+ }
+ public override void Close()
+ {
+ s.Close();
+ }
+ public override void Flush()
+ {
+ s.Flush();
+ }
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ return s.Seek(offset, origin);
+ }
+ public override void SetLength(long value)
+ {
+ s.SetLength(value);
+ }
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ return s.Read(buffer, offset, count);
+ }
+ public override int ReadByte()
+ {
+ return s.ReadByte();
+ }
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ s.Write(buffer, offset, count);
+ }
+ public override void WriteByte(byte value)
+ {
+ s.WriteByte(value);
+ }
+ protected readonly Stream s;
+ }
+}
diff --git a/crypto/src/x509/X509Certificate.cs b/crypto/src/x509/X509Certificate.cs
index f156f3147..4487232f0 100644
--- a/crypto/src/x509/X509Certificate.cs
+++ b/crypto/src/x509/X509Certificate.cs
@@ -14,6 +14,7 @@ using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.X509.Extension;
+using Org.BouncyCastle.Crypto.Operators;
namespace Org.BouncyCastle.X509
{
@@ -546,30 +547,38 @@ namespace Org.BouncyCastle.X509
public virtual void Verify(
AsymmetricKeyParameter key)
{
- string sigName = X509SignatureUtilities.GetSignatureName(c.SignatureAlgorithm);
- ISigner signature = SignerUtilities.GetSigner(sigName);
-
- CheckSignature(key, signature);
+ CheckSignature(new Asn1SignatureVerifier(c.SignatureAlgorithm, key));
}
- protected virtual void CheckSignature(
- AsymmetricKeyParameter publicKey,
- ISigner signature)
+ /// <summary>
+ /// Verify the certificate's signature using a verifier created using the passed in verifier provider.
+ /// </summary>
+ /// <param name="verifierProvider">An appropriate provider for verifying the certificate's signature.</param>
+ /// <returns>True if the signature is valid.</returns>
+ /// <exception cref="Exception">If verifier provider is not appropriate or the certificate algorithm is invalid.</exception>
+ public virtual void Verify(
+ ISignatureVerifierProvider verifierProvider)
+ {
+ CheckSignature(verifierProvider.CreateSignatureVerifier (c.SignatureAlgorithm));
+ }
+
+ protected virtual void CheckSignature(
+ ISignatureVerifier verifier)
{
if (!IsAlgIDEqual(c.SignatureAlgorithm, c.TbsCertificate.Signature))
throw new CertificateException("signature algorithm in TBS cert not same as outer cert");
Asn1Encodable parameters = c.SignatureAlgorithm.Parameters;
- X509SignatureUtilities.SetSignatureParameters(signature, parameters);
-
- signature.Init(false, publicKey);
+ IStreamCalculator streamCalculator = verifier.CreateCalculator();
byte[] b = this.GetTbsCertificate();
- signature.BlockUpdate(b, 0, b.Length);
- byte[] sig = this.GetSignature();
- if (!signature.VerifySignature(sig))
+ streamCalculator.Stream.Write(b, 0, b.Length);
+
+ streamCalculator.Stream.Close();
+
+ if (!((IVerifier)streamCalculator.GetResult()).IsVerified(this.GetSignature()))
{
throw new InvalidKeyException("Public key presented not for certificate signature");
}
diff --git a/crypto/src/x509/X509Crl.cs b/crypto/src/x509/X509Crl.cs
index 7d0e7aa72..1746960fb 100644
--- a/crypto/src/x509/X509Crl.cs
+++ b/crypto/src/x509/X509Crl.cs
@@ -14,6 +14,7 @@ using Org.BouncyCastle.Utilities.Collections;
using Org.BouncyCastle.Utilities.Date;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.X509.Extension;
+using Org.BouncyCastle.Crypto.Operators;
namespace Org.BouncyCastle.X509
{
@@ -83,24 +84,46 @@ namespace Org.BouncyCastle.X509
public virtual void Verify(
AsymmetricKeyParameter publicKey)
{
- if (!c.SignatureAlgorithm.Equals(c.TbsCertList.Signature))
- {
- throw new CrlException("Signature algorithm on CertificateList does not match TbsCertList.");
- }
+ Verify(new Asn1SignatureVerifierProvider(publicKey));
+ }
- ISigner sig = SignerUtilities.GetSigner(SigAlgName);
- sig.Init(false, publicKey);
+ /// <summary>
+ /// Verify the CRL's signature using a verifier created using the passed in verifier provider.
+ /// </summary>
+ /// <param name="verifierProvider">An appropriate provider for verifying the CRL's signature.</param>
+ /// <returns>True if the signature is valid.</returns>
+ /// <exception cref="Exception">If verifier provider is not appropriate or the CRL algorithm is invalid.</exception>
+ public virtual void Verify(
+ ISignatureVerifierProvider verifierProvider)
+ {
+ CheckSignature(verifierProvider.CreateSignatureVerifier(c.SignatureAlgorithm));
+ }
- byte[] encoded = this.GetTbsCertList();
- sig.BlockUpdate(encoded, 0, encoded.Length);
+ protected virtual void CheckSignature(
+ ISignatureVerifier verifier)
+ {
+ if (!c.SignatureAlgorithm.Equals(c.TbsCertList.Signature))
+ {
+ throw new CrlException("Signature algorithm on CertificateList does not match TbsCertList.");
+ }
- if (!sig.VerifySignature(this.GetSignature()))
- {
- throw new SignatureException("CRL does not verify with supplied public key.");
- }
- }
+ Asn1Encodable parameters = c.SignatureAlgorithm.Parameters;
+
+ IStreamCalculator streamCalculator = verifier.CreateCalculator();
+
+ byte[] b = this.GetTbsCertList();
+
+ streamCalculator.Stream.Write(b, 0, b.Length);
+
+ streamCalculator.Stream.Close();
+
+ if (!((IVerifier)streamCalculator.GetResult()).IsVerified(this.GetSignature()))
+ {
+ throw new InvalidKeyException("CRL does not verify with supplied public key.");
+ }
+ }
- public virtual int Version
+ public virtual int Version
{
get { return c.Version; }
}
diff --git a/crypto/src/x509/X509V1CertificateGenerator.cs b/crypto/src/x509/X509V1CertificateGenerator.cs
index 02b58a198..a452df440 100644
--- a/crypto/src/x509/X509V1CertificateGenerator.cs
+++ b/crypto/src/x509/X509V1CertificateGenerator.cs
@@ -1,10 +1,12 @@
using System;
+using System.IO;
using System.Collections;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Operators;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Security.Certificates;
@@ -119,6 +121,7 @@ namespace Org.BouncyCastle.X509
/// This can be either a name or an OID, names are treated as case insensitive.
/// </summary>
/// <param name="signatureAlgorithm">string representation of the algorithm name</param>
+ [Obsolete("Not needed if Generate used with an ISignatureCalculator")]
public void SetSignatureAlgorithm(
string signatureAlgorithm)
{
@@ -143,6 +146,7 @@ namespace Org.BouncyCastle.X509
/// </summary>
/// <param name="privateKey">The private key of the issuer used to sign this certificate.</param>
/// <returns>An X509Certificate.</returns>
+ [Obsolete("Use Generate with an ISignatureCalculator")]
public X509Certificate Generate(
AsymmetricKeyParameter privateKey)
{
@@ -155,43 +159,43 @@ namespace Org.BouncyCastle.X509
/// <param name="privateKey">The private key of the issuer used to sign this certificate.</param>
/// <param name="random">The Secure Random you want to use.</param>
/// <returns>An X509Certificate.</returns>
+ [Obsolete("Use Generate with an ISignatureCalculator")]
public X509Certificate Generate(
AsymmetricKeyParameter privateKey,
SecureRandom random)
{
+ return Generate(new Asn1SignatureCalculator(signatureAlgorithm, privateKey, random));
+ }
+
+ /// <summary>
+ /// Generate a new X509Certificate using the passed in SignatureCalculator.
+ /// </summary>
+ /// <param name="signatureCalculator">A signature calculator with the necessary algorithm details.</param>
+ /// <returns>An X509Certificate.</returns>
+ public X509Certificate Generate(ISignatureCalculator signatureCalculator)
+ {
+ tbsGen.SetSignature ((AlgorithmIdentifier)signatureCalculator.AlgorithmDetails);
+
TbsCertificateStructure tbsCert = tbsGen.GenerateTbsCertificate();
- byte[] signature;
- try
- {
- signature = X509Utilities.GetSignatureForObject(
- sigOID, signatureAlgorithm, privateKey, random, tbsCert);
- }
- catch (Exception e)
- {
- // TODO
-// throw new ExtCertificateEncodingException("exception encoding TBS cert", e);
- throw new CertificateEncodingException("exception encoding TBS cert", e);
- }
+ IStreamCalculator streamCalculator = signatureCalculator.CreateCalculator();
- try
- {
- return GenerateJcaObject(tbsCert, signature);
- }
- catch (CertificateParsingException e)
- {
- // TODO
- // throw new ExtCertificateEncodingException("exception producing certificate object", e);
- throw new CertificateEncodingException("exception producing certificate object", e);
- }
+ byte[] encoded = tbsCert.GetDerEncoded();
+
+ streamCalculator.Stream.Write(encoded, 0, encoded.Length);
+
+ streamCalculator.Stream.Close();
+
+ return GenerateJcaObject(tbsCert, (AlgorithmIdentifier)signatureCalculator.AlgorithmDetails, ((IBlockResult)streamCalculator.GetResult()).DoFinal());
}
private X509Certificate GenerateJcaObject(
TbsCertificateStructure tbsCert,
+ AlgorithmIdentifier sigAlg,
byte[] signature)
{
return new X509Certificate(
- new X509CertificateStructure(tbsCert, sigAlgId, new DerBitString(signature)));
+ new X509CertificateStructure(tbsCert, sigAlg, new DerBitString(signature)));
}
/// <summary>
diff --git a/crypto/src/x509/X509V2AttributeCertificate.cs b/crypto/src/x509/X509V2AttributeCertificate.cs
index 117ac4cc2..cc72c23bb 100644
--- a/crypto/src/x509/X509V2AttributeCertificate.cs
+++ b/crypto/src/x509/X509V2AttributeCertificate.cs
@@ -9,6 +9,7 @@ using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Crypto.Operators;
namespace Org.BouncyCastle.X509
{
@@ -151,29 +152,48 @@ namespace Org.BouncyCastle.X509
return cert.SignatureValue.GetBytes();
}
- public virtual void Verify(
- AsymmetricKeyParameter publicKey)
- {
- if (!cert.SignatureAlgorithm.Equals(cert.ACInfo.Signature))
+ public virtual void Verify(
+ AsymmetricKeyParameter key)
+ {
+ CheckSignature(new Asn1SignatureVerifier(cert.SignatureAlgorithm, key));
+ }
+
+ /// <summary>
+ /// Verify the certificate's signature using a verifier created using the passed in verifier provider.
+ /// </summary>
+ /// <param name="verifierProvider">An appropriate provider for verifying the certificate's signature.</param>
+ /// <returns>True if the signature is valid.</returns>
+ /// <exception cref="Exception">If verifier provider is not appropriate or the certificate algorithm is invalid.</exception>
+ public virtual void Verify(
+ ISignatureVerifierProvider verifierProvider)
+ {
+ CheckSignature(verifierProvider.CreateSignatureVerifier(cert.SignatureAlgorithm));
+ }
+
+ protected virtual void CheckSignature(
+ ISignatureVerifier verifier)
+ {
+ if (!cert.SignatureAlgorithm.Equals(cert.ACInfo.Signature))
{
throw new CertificateException("Signature algorithm in certificate info not same as outer certificate");
}
- ISigner signature = SignerUtilities.GetSigner(cert.SignatureAlgorithm.ObjectID.Id);
-
- signature.Init(false, publicKey);
+ IStreamCalculator streamCalculator = verifier.CreateCalculator();
try
{
- byte[] b = cert.ACInfo.GetEncoded();
- signature.BlockUpdate(b, 0, b.Length);
- }
+ byte[] b = this.cert.ACInfo.GetEncoded();
+
+ streamCalculator.Stream.Write(b, 0, b.Length);
+
+ streamCalculator.Stream.Close();
+ }
catch (IOException e)
{
throw new SignatureException("Exception encoding certificate info object", e);
}
- if (!signature.VerifySignature(this.GetSignature()))
+ if (!((IVerifier)streamCalculator.GetResult()).IsVerified(this.GetSignature()))
{
throw new InvalidKeyException("Public key presented not for certificate signature");
}
diff --git a/crypto/src/x509/X509V2AttributeCertificateGenerator.cs b/crypto/src/x509/X509V2AttributeCertificateGenerator.cs
index a683d5e20..138f2ec6f 100644
--- a/crypto/src/x509/X509V2AttributeCertificateGenerator.cs
+++ b/crypto/src/x509/X509V2AttributeCertificateGenerator.cs
@@ -8,6 +8,8 @@ using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Crypto.Operators;
+using System.IO;
namespace Org.BouncyCastle.X509
{
@@ -66,12 +68,13 @@ namespace Org.BouncyCastle.X509
acInfoGen.SetEndDate(new DerGeneralizedTime(date));
}
- /// <summary>
- /// Set the signature algorithm. This can be either a name or an OID, names
- /// are treated as case insensitive.
- /// </summary>
- /// <param name="signatureAlgorithm">The algorithm name.</param>
- public void SetSignatureAlgorithm(
+ /// <summary>
+ /// Set the signature algorithm. This can be either a name or an OID, names
+ /// are treated as case insensitive.
+ /// </summary>
+ /// <param name="signatureAlgorithm">The algorithm name.</param>
+ [Obsolete("Not needed if Generate used with an ISignatureCalculator")]
+ public void SetSignatureAlgorithm(
string signatureAlgorithm)
{
this.signatureAlgorithm = signatureAlgorithm;
@@ -127,37 +130,57 @@ namespace Org.BouncyCastle.X509
extGenerator.AddExtension(new DerObjectIdentifier(oid), critical, extensionValue);
}
- /// <summary>
- /// Generate an X509 certificate, based on the current issuer and subject.
- /// </summary>
- public IX509AttributeCertificate Generate(
- AsymmetricKeyParameter publicKey)
+ /// <summary>
+ /// Generate an X509 certificate, based on the current issuer and subject.
+ /// </summary>
+ [Obsolete("Use Generate with an ISignatureCalculator")]
+ public IX509AttributeCertificate Generate(
+ AsymmetricKeyParameter privateKey)
{
- return Generate(publicKey, null);
+ return Generate(privateKey, null);
}
- /// <summary>
- /// Generate an X509 certificate, based on the current issuer and subject,
- /// using the supplied source of randomness, if required.
- /// </summary>
- public IX509AttributeCertificate Generate(
- AsymmetricKeyParameter publicKey,
+ /// <summary>
+ /// Generate an X509 certificate, based on the current issuer and subject,
+ /// using the supplied source of randomness, if required.
+ /// </summary>
+ [Obsolete("Use Generate with an ISignatureCalculator")]
+ public IX509AttributeCertificate Generate(
+ AsymmetricKeyParameter privateKey,
SecureRandom random)
- {
- if (!extGenerator.IsEmpty)
+ {
+ return Generate(new Asn1SignatureCalculator(signatureAlgorithm, privateKey, random));
+ }
+
+ /// <summary>
+ /// Generate a new X.509 Attribute Certificate using the passed in SignatureCalculator.
+ /// </summary>
+ /// <param name="signatureCalculator">A signature calculator with the necessary algorithm details.</param>
+ /// <returns>An IX509AttributeCertificate.</returns>
+ public IX509AttributeCertificate Generate(ISignatureCalculator signatureCalculator)
+ {
+ if (!extGenerator.IsEmpty)
{
acInfoGen.SetExtensions(extGenerator.Generate());
}
AttributeCertificateInfo acInfo = acInfoGen.GenerateAttributeCertificateInfo();
- Asn1EncodableVector v = new Asn1EncodableVector();
+ byte[] encoded = acInfo.GetDerEncoded();
+
+ IStreamCalculator streamCalculator = signatureCalculator.CreateCalculator();
+
+ streamCalculator.Stream.Write(encoded, 0, encoded.Length);
+
+ streamCalculator.Stream.Close();
+
+ Asn1EncodableVector v = new Asn1EncodableVector();
- v.Add(acInfo, sigAlgId);
+ v.Add(acInfo, (AlgorithmIdentifier)signatureCalculator.AlgorithmDetails);
try
{
- v.Add(new DerBitString(X509Utilities.GetSignatureForObject(sigOID, signatureAlgorithm, publicKey, random, acInfo)));
+ v.Add(new DerBitString(((IBlockResult)streamCalculator.GetResult()).DoFinal()));
return new X509V2AttributeCertificate(AttributeCertificate.GetInstance(new DerSequence(v)));
}
diff --git a/crypto/src/x509/X509V2CRLGenerator.cs b/crypto/src/x509/X509V2CRLGenerator.cs
index a2293b333..c1cc8e824 100644
--- a/crypto/src/x509/X509V2CRLGenerator.cs
+++ b/crypto/src/x509/X509V2CRLGenerator.cs
@@ -10,6 +10,7 @@ using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Crypto.Operators;
namespace Org.BouncyCastle.X509
{
@@ -129,13 +130,12 @@ namespace Org.BouncyCastle.X509
}
}
- /**
- * Set the signature algorithm. This can be either a name or an oid, names
- * are treated as case insensitive.
- *
- * @param signatureAlgorithm string representation of the algorithm name.
- */
- public void SetSignatureAlgorithm(
+ /// <summary>
+ /// Set the signature algorithm that will be used to sign this CRL.
+ /// </summary>
+ /// <param name="signatureAlgorithm"/>
+ [Obsolete("Not needed if Generate used with an ISignatureCalculator")]
+ public void SetSignatureAlgorithm(
string signatureAlgorithm)
{
this.signatureAlgorithm = signatureAlgorithm;
@@ -198,40 +198,55 @@ namespace Org.BouncyCastle.X509
extGenerator.AddExtension(oid, critical, new DerOctetString(extensionValue));
}
- /// <summary>Generate an X509 CRL, based on the current issuer and subject.</summary>
- /// <param name="privateKey">The key used for signing.</param>
- public X509Crl Generate(
- AsymmetricKeyParameter privateKey)
- {
- return Generate(privateKey, null);
- }
+ /// <summary>
+ /// Generate an X.509 CRL, based on the current issuer and subject.
+ /// </summary>
+ /// <param name="privateKey">The private key of the issuer that is signing this certificate.</param>
+ /// <returns>An X509Crl.</returns>
+ [Obsolete("Use Generate with an ISignatureCalculator")]
+ public X509Crl Generate(
+ AsymmetricKeyParameter privateKey)
+ {
+ return Generate(privateKey, null);
+ }
- /// <summary>Generate an X509 CRL, based on the current issuer and subject.</summary>
- /// <param name="privateKey">The key used for signing.</param>
- /// <param name="random">A user-defined source of randomness.</param>
- public X509Crl Generate(
- AsymmetricKeyParameter privateKey,
- SecureRandom random)
- {
- TbsCertificateList tbsCrl = GenerateCertList();
- byte[] signature;
+ /// <summary>
+ /// Generate an X.509 CRL, based on the current issuer and subject using the specified secure random.
+ /// </summary>
+ /// <param name="privateKey">The private key of the issuer that is signing this certificate.</param>
+ /// <param name="random">Your Secure Random instance.</param>
+ /// <returns>An X509Crl.</returns>
+ [Obsolete("Use Generate with an ISignatureCalculator")]
+ public X509Crl Generate(
+ AsymmetricKeyParameter privateKey,
+ SecureRandom random)
+ {
+ return Generate(new Asn1SignatureCalculator(signatureAlgorithm, privateKey, random));
+ }
- try
- {
- signature = X509Utilities.GetSignatureForObject(
- sigOID, signatureAlgorithm, privateKey, random, tbsCrl);
- }
- catch (IOException e)
- {
- // TODO
-// throw new ExtCrlException("cannot generate CRL encoding", e);
- throw new CrlException("cannot generate CRL encoding", e);
- }
+ /// <summary>
+ /// Generate a new X509Crl using the passed in SignatureCalculator.
+ /// </summary>
+ /// <param name="signatureCalculator">A signature calculator with the necessary algorithm details.</param>
+ /// <returns>An X509Crl.</returns>
+ public X509Crl Generate(ISignatureCalculator signatureCalculator)
+ {
+ tbsGen.SetSignature((AlgorithmIdentifier)signatureCalculator.AlgorithmDetails);
- return GenerateJcaObject(tbsCrl, signature);
- }
+ TbsCertificateList tbsCertList = GenerateCertList();
+
+ IStreamCalculator streamCalculator = signatureCalculator.CreateCalculator();
+
+ byte[] encoded = tbsCertList.GetDerEncoded();
+
+ streamCalculator.Stream.Write(encoded, 0, encoded.Length);
+
+ streamCalculator.Stream.Close();
+
+ return GenerateJcaObject(tbsCertList, (AlgorithmIdentifier)signatureCalculator.AlgorithmDetails, ((IBlockResult)streamCalculator.GetResult()).DoFinal());
+ }
- private TbsCertificateList GenerateCertList()
+ private TbsCertificateList GenerateCertList()
{
if (!extGenerator.IsEmpty)
{
@@ -243,11 +258,12 @@ namespace Org.BouncyCastle.X509
private X509Crl GenerateJcaObject(
TbsCertificateList tbsCrl,
+ AlgorithmIdentifier algId,
byte[] signature)
{
return new X509Crl(
CertificateList.GetInstance(
- new DerSequence(tbsCrl, sigAlgId, new DerBitString(signature))));
+ new DerSequence(tbsCrl, algId, new DerBitString(signature))));
}
/// <summary>
diff --git a/crypto/src/x509/X509V3CertificateGenerator.cs b/crypto/src/x509/X509V3CertificateGenerator.cs
index bb0dd9cbc..a22cd9943 100644
--- a/crypto/src/x509/X509V3CertificateGenerator.cs
+++ b/crypto/src/x509/X509V3CertificateGenerator.cs
@@ -1,9 +1,11 @@
using System;
using System.Collections;
+using System.IO;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Operators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
@@ -110,6 +112,7 @@ namespace Org.BouncyCastle.X509
/// Set the signature algorithm that will be used to sign this certificate.
/// </summary>
/// <param name="signatureAlgorithm"/>
+ [Obsolete("Not needed if Generate used with an ISignatureCalculator")]
public void SetSignatureAlgorithm(
string signatureAlgorithm)
{
@@ -274,7 +277,8 @@ namespace Org.BouncyCastle.X509
/// </summary>
/// <param name="privateKey">The private key of the issuer that is signing this certificate.</param>
/// <returns>An X509Certificate.</returns>
- public X509Certificate Generate(
+ [Obsolete("Use Generate with an ISignatureCalculator")]
+ public X509Certificate Generate(
AsymmetricKeyParameter privateKey)
{
return Generate(privateKey, null);
@@ -286,53 +290,48 @@ namespace Org.BouncyCastle.X509
/// <param name="privateKey">The private key of the issuer that is signing this certificate.</param>
/// <param name="random">You Secure Random instance.</param>
/// <returns>An X509Certificate.</returns>
+ [Obsolete("Use Generate with an ISignatureCalculator")]
public X509Certificate Generate(
AsymmetricKeyParameter privateKey,
SecureRandom random)
{
- TbsCertificateStructure tbsCert = GenerateTbsCert();
- byte[] signature;
-
- try
- {
- signature = X509Utilities.GetSignatureForObject(
- sigOid, signatureAlgorithm, privateKey, random, tbsCert);
- }
- catch (Exception e)
- {
- // TODO
-// throw new ExtCertificateEncodingException("exception encoding TBS cert", e);
- throw new CertificateEncodingException("exception encoding TBS cert", e);
- }
-
- try
- {
- return GenerateJcaObject(tbsCert, signature);
- }
- catch (CertificateParsingException e)
- {
- // TODO
- // throw new ExtCertificateEncodingException("exception producing certificate object", e);
- throw new CertificateEncodingException("exception producing certificate object", e);
- }
+ return Generate(new Asn1SignatureCalculator(signatureAlgorithm, privateKey, random));
}
- private TbsCertificateStructure GenerateTbsCert()
+ /// <summary>
+ /// Generate a new X509Certificate using the passed in SignatureCalculator.
+ /// </summary>
+ /// <param name="signatureCalculator">A signature calculator with the necessary algorithm details.</param>
+ /// <returns>An X509Certificate.</returns>
+ public X509Certificate Generate(ISignatureCalculator signatureCalculator)
{
- if (!extGenerator.IsEmpty)
- {
- tbsGen.SetExtensions(extGenerator.Generate());
- }
+ tbsGen.SetSignature ((AlgorithmIdentifier)signatureCalculator.AlgorithmDetails);
+
+ if (!extGenerator.IsEmpty)
+ {
+ tbsGen.SetExtensions(extGenerator.Generate());
+ }
+
+ TbsCertificateStructure tbsCert = tbsGen.GenerateTbsCertificate();
+
+ IStreamCalculator streamCalculator = signatureCalculator.CreateCalculator();
+
+ byte[] encoded = tbsCert.GetDerEncoded();
+
+ streamCalculator.Stream.Write (encoded, 0, encoded.Length);
+
+ streamCalculator.Stream.Close ();
- return tbsGen.GenerateTbsCertificate();
+ return GenerateJcaObject(tbsCert, (AlgorithmIdentifier)signatureCalculator.AlgorithmDetails, ((IBlockResult)streamCalculator.GetResult()).DoFinal());
}
private X509Certificate GenerateJcaObject(
TbsCertificateStructure tbsCert,
+ AlgorithmIdentifier sigAlg,
byte[] signature)
{
return new X509Certificate(
- new X509CertificateStructure(tbsCert, sigAlgId, new DerBitString(signature)));
+ new X509CertificateStructure(tbsCert, sigAlg, new DerBitString(signature)));
}
/// <summary>
|