Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
T
Titanium-Web-Proxy
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Titanium-Web-Proxy
Commits
24c5332d
Commit
24c5332d
authored
Sep 24, 2020
by
Honfika
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix after #795
parent
c54c7c1c
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
244 additions
and
236 deletions
+244
-236
BCCertificateMaker.cs
src/Titanium.Web.Proxy/Certificates/BCCertificateMaker.cs
+236
-235
BCCertificateMakerFast.cs
...Titanium.Web.Proxy/Certificates/BCCertificateMakerFast.cs
+8
-1
No files found.
src/Titanium.Web.Proxy/Certificates/BCCertificateMaker.cs
View file @
24c5332d
using
System
;
using
System
;
using
System.IO
;
using
System.IO
;
using
System.Net
;
using
System.Net
;
using
System.Security.Cryptography.X509Certificates
;
using
System.Security.Cryptography.X509Certificates
;
using
Org.BouncyCastle.Asn1
;
using
Org.BouncyCastle.Asn1
;
using
Org.BouncyCastle.Asn1.Pkcs
;
using
Org.BouncyCastle.Asn1.Pkcs
;
using
Org.BouncyCastle.Asn1.X509
;
using
Org.BouncyCastle.Asn1.X509
;
using
Org.BouncyCastle.Crypto
;
using
Org.BouncyCastle.Crypto
;
using
Org.BouncyCastle.Crypto.Generators
;
using
Org.BouncyCastle.Crypto.Generators
;
using
Org.BouncyCastle.Crypto.Operators
;
using
Org.BouncyCastle.Crypto.Operators
;
using
Org.BouncyCastle.Crypto.Parameters
;
using
Org.BouncyCastle.Crypto.Parameters
;
using
Org.BouncyCastle.Crypto.Prng
;
using
Org.BouncyCastle.Crypto.Prng
;
using
Org.BouncyCastle.Math
;
using
Org.BouncyCastle.Math
;
using
Org.BouncyCastle.OpenSsl
;
using
Org.BouncyCastle.OpenSsl
;
using
Org.BouncyCastle.Pkcs
;
using
Org.BouncyCastle.Pkcs
;
using
Org.BouncyCastle.Security
;
using
Org.BouncyCastle.Security
;
using
Org.BouncyCastle.Utilities
;
using
Org.BouncyCastle.Utilities
;
using
Org.BouncyCastle.X509
;
using
Org.BouncyCastle.X509
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Shared
;
using
Titanium.Web.Proxy.Shared
;
using
X509Certificate
=
Org
.
BouncyCastle
.
X509
.
X509Certificate
;
using
X509Certificate
=
Org
.
BouncyCastle
.
X509
.
X509Certificate
;
namespace
Titanium.Web.Proxy.Network.Certificate
namespace
Titanium.Web.Proxy.Network.Certificate
{
{
/// <summary>
/// <summary>
/// Implements certificate generation operations.
/// Implements certificate generation operations.
/// </summary>
/// </summary>
internal
class
BCCertificateMaker
:
ICertificateMaker
internal
class
BCCertificateMaker
:
ICertificateMaker
{
{
private
readonly
int
certificateValidDays
;
private
readonly
int
certificateValidDays
;
private
const
int
certificateGraceDays
=
366
;
private
const
int
certificateGraceDays
=
366
;
// The FriendlyName value cannot be set on Unix.
// The FriendlyName value cannot be set on Unix.
// Set this flag to true when exception detected to avoid further exceptions
// Set this flag to true when exception detected to avoid further exceptions
private
static
bool
doNotSetFriendlyName
;
private
static
bool
doNotSetFriendlyName
;
private
readonly
ExceptionHandler
exceptionFunc
;
private
readonly
ExceptionHandler
exceptionFunc
;
internal
BCCertificateMaker
(
ExceptionHandler
exceptionFunc
,
int
certificateValidDays
)
internal
BCCertificateMaker
(
ExceptionHandler
exceptionFunc
,
int
certificateValidDays
)
{
{
this
.
certificateValidDays
=
certificateValidDays
;
this
.
certificateValidDays
=
certificateValidDays
;
this
.
exceptionFunc
=
exceptionFunc
;
this
.
exceptionFunc
=
exceptionFunc
;
}
}
/// <summary>
/// <summary>
/// Makes the certificate.
/// Makes the certificate.
/// </summary>
/// </summary>
/// <param name="sSubjectCn">The s subject cn.</param>
/// <param name="sSubjectCn">The s subject cn.</param>
/// <param name="signingCert">The signing cert.</param>
/// <param name="signingCert">The signing cert.</param>
/// <returns>X509Certificate2 instance.</returns>
/// <returns>X509Certificate2 instance.</returns>
public
X509Certificate2
MakeCertificate
(
string
sSubjectCn
,
X509Certificate2
?
signingCert
=
null
)
public
X509Certificate2
MakeCertificate
(
string
sSubjectCn
,
X509Certificate2
?
signingCert
=
null
)
{
{
return
makeCertificateInternal
(
sSubjectCn
,
true
,
signingCert
);
return
makeCertificateInternal
(
sSubjectCn
,
true
,
signingCert
);
}
}
/// <summary>
/// <summary>
/// Generates the certificate.
/// Generates the certificate.
/// </summary>
/// </summary>
/// <param name="subjectName">Name of the subject.</param>
/// <param name="subjectName">Name of the subject.</param>
/// <param name="issuerName">Name of the issuer.</param>
/// <param name="issuerName">Name of the issuer.</param>
/// <param name="validFrom">The valid from.</param>
/// <param name="validFrom">The valid from.</param>
/// <param name="validTo">The valid to.</param>
/// <param name="validTo">The valid to.</param>
/// <param name="keyStrength">The key strength.</param>
/// <param name="keyStrength">The key strength.</param>
/// <param name="signatureAlgorithm">The signature algorithm.</param>
/// <param name="signatureAlgorithm">The signature algorithm.</param>
/// <param name="issuerPrivateKey">The issuer private key.</param>
/// <param name="issuerPrivateKey">The issuer private key.</param>
/// <param name="hostName">The host name</param>
/// <param name="hostName">The host name</param>
/// <returns>X509Certificate2 instance.</returns>
/// <returns>X509Certificate2 instance.</returns>
/// <exception cref="PemException">Malformed sequence in RSA private key</exception>
/// <exception cref="PemException">Malformed sequence in RSA private key</exception>
private
static
X509Certificate2
generateCertificate
(
string
?
hostName
,
private
static
X509Certificate2
generateCertificate
(
string
?
hostName
,
string
subjectName
,
string
subjectName
,
string
issuerName
,
DateTime
validFrom
,
string
issuerName
,
DateTime
validFrom
,
DateTime
validTo
,
int
keyStrength
=
2048
,
DateTime
validTo
,
int
keyStrength
=
2048
,
string
signatureAlgorithm
=
"SHA256WithRSA"
,
string
signatureAlgorithm
=
"SHA256WithRSA"
,
AsymmetricKeyParameter
?
issuerPrivateKey
=
null
)
AsymmetricKeyParameter
?
issuerPrivateKey
=
null
)
{
{
// Generating Random Numbers
// Generating Random Numbers
var
randomGenerator
=
new
CryptoApiRandomGenerator
();
var
randomGenerator
=
new
CryptoApiRandomGenerator
();
var
secureRandom
=
new
SecureRandom
(
randomGenerator
);
var
secureRandom
=
new
SecureRandom
(
randomGenerator
);
// The Certificate Generator
// The Certificate Generator
var
certificateGenerator
=
new
X509V3CertificateGenerator
();
var
certificateGenerator
=
new
X509V3CertificateGenerator
();
// Serial Number
// Serial Number
var
serialNumber
=
var
serialNumber
=
BigIntegers
.
CreateRandomInRange
(
BigInteger
.
One
,
BigInteger
.
ValueOf
(
long
.
MaxValue
),
secureRandom
);
BigIntegers
.
CreateRandomInRange
(
BigInteger
.
One
,
BigInteger
.
ValueOf
(
long
.
MaxValue
),
secureRandom
);
certificateGenerator
.
SetSerialNumber
(
serialNumber
);
certificateGenerator
.
SetSerialNumber
(
serialNumber
);
// Issuer and Subject Name
// Issuer and Subject Name
var
subjectDn
=
new
X509Name
(
subjectName
);
var
subjectDn
=
new
X509Name
(
subjectName
);
var
issuerDn
=
new
X509Name
(
issuerName
);
var
issuerDn
=
new
X509Name
(
issuerName
);
certificateGenerator
.
SetIssuerDN
(
issuerDn
);
certificateGenerator
.
SetIssuerDN
(
issuerDn
);
certificateGenerator
.
SetSubjectDN
(
subjectDn
);
certificateGenerator
.
SetSubjectDN
(
subjectDn
);
certificateGenerator
.
SetNotBefore
(
validFrom
);
certificateGenerator
.
SetNotBefore
(
validFrom
);
certificateGenerator
.
SetNotAfter
(
validTo
);
certificateGenerator
.
SetNotAfter
(
validTo
);
if
(
hostName
!=
null
)
if
(
hostName
!=
null
)
{
{
// add subject alternative names
// add subject alternative names
var
nameType
=
GeneralName
.
DnsName
;
var
nameType
=
GeneralName
.
DnsName
;
if
(
IPAddress
.
TryParse
(
hostName
,
out
_
))
if
(
IPAddress
.
TryParse
(
hostName
,
out
_
))
{
{
nameType
=
GeneralName
.
IPAddress
;
nameType
=
GeneralName
.
IPAddress
;
}
}
var
subjectAlternativeNames
=
new
Asn1Encodable
[]
{
new
GeneralName
(
nameType
,
hostName
)
};
var
subjectAlternativeNames
=
new
Asn1Encodable
[]
{
new
GeneralName
(
nameType
,
hostName
)
};
var
subjectAlternativeNamesExtension
=
new
DerSequence
(
subjectAlternativeNames
);
certificateGenerator
.
AddExtension
(
X509Extensions
.
SubjectAlternativeName
.
Id
,
false
,
var
subjectAlternativeNamesExtension
=
new
DerSequence
(
subjectAlternativeNames
);
subjectAlternativeNamesExtension
);
certificateGenerator
.
AddExtension
(
X509Extensions
.
SubjectAlternativeName
.
Id
,
false
,
}
subjectAlternativeNamesExtension
);
}
// Subject Public Key
var
keyGenerationParameters
=
new
KeyGenerationParameters
(
secureRandom
,
keyStrength
);
// Subject Public Key
var
keyPairGenerator
=
new
RsaKeyPairGenerator
();
var
keyGenerationParameters
=
new
KeyGenerationParameters
(
secureRandom
,
keyStrength
);
keyPairGenerator
.
Init
(
keyGenerationParameters
);
var
keyPairGenerator
=
new
RsaKeyPairGenerator
();
var
subjectKeyPair
=
keyPairGenerator
.
GenerateKeyPair
();
keyPairGenerator
.
Init
(
keyGenerationParameters
);
var
subjectKeyPair
=
keyPairGenerator
.
GenerateKeyPair
();
certificateGenerator
.
SetPublicKey
(
subjectKeyPair
.
Public
);
certificateGenerator
.
SetPublicKey
(
subjectKeyPair
.
Public
);
// Set certificate intended purposes to only Server Authentication
certificateGenerator
.
AddExtension
(
X509Extensions
.
ExtendedKeyUsage
.
Id
,
false
,
// Set certificate intended purposes to only Server Authentication
new
ExtendedKeyUsage
(
KeyPurposeID
.
IdKPServerAuth
));
certificateGenerator
.
AddExtension
(
X509Extensions
.
ExtendedKeyUsage
.
Id
,
false
,
if
(
issuerPrivateKey
==
null
)
new
ExtendedKeyUsage
(
KeyPurposeID
.
IdKPServerAuth
));
{
if
(
issuerPrivateKey
==
null
)
certificateGenerator
.
AddExtension
(
X509Extensions
.
BasicConstraints
.
Id
,
true
,
new
BasicConstraints
(
true
));
{
}
certificateGenerator
.
AddExtension
(
X509Extensions
.
BasicConstraints
.
Id
,
true
,
new
BasicConstraints
(
true
));
}
var
signatureFactory
=
new
Asn1SignatureFactory
(
signatureAlgorithm
,
issuerPrivateKey
??
subjectKeyPair
.
Private
,
secureRandom
);
var
signatureFactory
=
new
Asn1SignatureFactory
(
signatureAlgorithm
,
issuerPrivateKey
??
subjectKeyPair
.
Private
,
secureRandom
);
// Self-sign the certificate
var
certificate
=
certificateGenerator
.
Generate
(
signatureFactory
);
// Self-sign the certificate
var
certificate
=
certificateGenerator
.
Generate
(
signatureFactory
);
// Corresponding private key
var
privateKeyInfo
=
PrivateKeyInfoFactory
.
CreatePrivateKeyInfo
(
subjectKeyPair
.
Private
);
// Corresponding private key
var
privateKeyInfo
=
PrivateKeyInfoFactory
.
CreatePrivateKeyInfo
(
subjectKeyPair
.
Private
);
var
seq
=
(
Asn1Sequence
)
Asn1Object
.
FromByteArray
(
privateKeyInfo
.
ParsePrivateKey
().
GetDerEncoded
());
var
seq
=
(
Asn1Sequence
)
Asn1Object
.
FromByteArray
(
privateKeyInfo
.
ParsePrivateKey
().
GetDerEncoded
());
if
(
seq
.
Count
!=
9
)
{
if
(
seq
.
Count
!=
9
)
throw
new
PemException
(
"Malformed sequence in RSA private key"
);
{
}
throw
new
PemException
(
"Malformed sequence in RSA private key"
);
}
var
rsa
=
RsaPrivateKeyStructure
.
GetInstance
(
seq
);
var
rsaparams
=
new
RsaPrivateCrtKeyParameters
(
rsa
.
Modulus
,
rsa
.
PublicExponent
,
rsa
.
PrivateExponent
,
var
rsa
=
RsaPrivateKeyStructure
.
GetInstance
(
seq
);
rsa
.
Prime1
,
rsa
.
Prime2
,
rsa
.
Exponent1
,
var
rsaparams
=
new
RsaPrivateCrtKeyParameters
(
rsa
.
Modulus
,
rsa
.
PublicExponent
,
rsa
.
PrivateExponent
,
rsa
.
Exponent2
,
rsa
.
Coefficient
);
rsa
.
Prime1
,
rsa
.
Prime2
,
rsa
.
Exponent1
,
rsa
.
Exponent2
,
rsa
.
Coefficient
);
// Set private key onto certificate instance
var
x509Certificate
=
withPrivateKey
(
certificate
,
rsaparams
);
// Set private key onto certificate instance
var
x509Certificate
=
withPrivateKey
(
certificate
,
rsaparams
);
if
(!
doNotSetFriendlyName
)
{
if
(!
doNotSetFriendlyName
)
try
{
{
try
x509Certificate
.
FriendlyName
=
ProxyConstants
.
CNRemoverRegex
.
Replace
(
subjectName
,
string
.
Empty
);
{
}
x509Certificate
.
FriendlyName
=
ProxyConstants
.
CNRemoverRegex
.
Replace
(
subjectName
,
string
.
Empty
);
catch
(
PlatformNotSupportedException
)
}
{
catch
(
PlatformNotSupportedException
)
doNotSetFriendlyName
=
true
;
{
}
doNotSetFriendlyName
=
true
;
}
}
}
return
x509Certificate
;
}
return
x509Certificate
;
}
private
static
X509Certificate2
withPrivateKey
(
X509Certificate
certificate
,
AsymmetricKeyParameter
privateKey
)
{
private
static
X509Certificate2
withPrivateKey
(
X509Certificate
certificate
,
AsymmetricKeyParameter
privateKey
)
const
string
password
=
"password"
;
{
Pkcs12Store
store
;
const
string
password
=
"password"
;
Pkcs12Store
store
;
if
(
RunTime
.
IsRunningOnMono
)
{
if
(
RunTime
.
IsRunningOnMono
)
var
builder
=
new
Pkcs12StoreBuilder
();
{
builder
.
SetUseDerEncoding
(
true
);
var
builder
=
new
Pkcs12StoreBuilder
();
store
=
builder
.
Build
();
builder
.
SetUseDerEncoding
(
true
);
}
store
=
builder
.
Build
();
else
}
{
else
store
=
new
Pkcs12Store
();
{
}
store
=
new
Pkcs12Store
();
}
var
entry
=
new
X509CertificateEntry
(
certificate
);
store
.
SetCertificateEntry
(
certificate
.
SubjectDN
.
ToString
(),
entry
);
var
entry
=
new
X509CertificateEntry
(
certificate
);
store
.
SetCertificateEntry
(
certificate
.
SubjectDN
.
ToString
(),
entry
);
store
.
SetKeyEntry
(
certificate
.
SubjectDN
.
ToString
(),
new
AsymmetricKeyEntry
(
privateKey
),
new
[]
{
entry
});
using
(
var
ms
=
new
MemoryStream
())
store
.
SetKeyEntry
(
certificate
.
SubjectDN
.
ToString
(),
new
AsymmetricKeyEntry
(
privateKey
),
new
[]
{
entry
});
{
using
(
var
ms
=
new
MemoryStream
())
store
.
Save
(
ms
,
password
.
ToCharArray
(),
new
SecureRandom
(
new
CryptoApiRandomGenerator
()));
{
store
.
Save
(
ms
,
password
.
ToCharArray
(),
new
SecureRandom
(
new
CryptoApiRandomGenerator
()));
return
new
X509Certificate2
(
ms
.
ToArray
(),
password
,
X509KeyStorageFlags
.
Exportable
);
}
return
new
X509Certificate2
(
ms
.
ToArray
(),
password
,
X509KeyStorageFlags
.
Exportable
);
}
}
}
/// <summary>
/// Makes the certificate internal.
/// <summary>
/// </summary>
/// Makes the certificate internal.
/// <param name="hostName">hostname for certificate</param>
/// </summary>
/// <param name="subjectName">The full subject.</param>
/// <param name="hostName">hostname for certificate</param>
/// <param name="validFrom">The valid from.</param>
/// <param name="subjectName">The full subject.</param>
/// <param name="validTo">The valid to.</param>
/// <param name="validFrom">The valid from.</param>
/// <param name="signingCertificate">The signing certificate.</param>
/// <param name="validTo">The valid to.</param>
/// <returns>X509Certificate2 instance.</returns>
/// <param name="signingCertificate">The signing certificate.</param>
/// <exception cref="System.ArgumentException">
/// <returns>X509Certificate2 instance.</returns>
/// You must specify a Signing Certificate if and only if you are not creating a
/// <exception cref="System.ArgumentException">
/// root.
/// You must specify a Signing Certificate if and only if you are not creating a
/// </exception>
/// root.
private
X509Certificate2
makeCertificateInternal
(
string
hostName
,
string
subjectName
,
/// </exception>
DateTime
validFrom
,
DateTime
validTo
,
X509Certificate2
?
signingCertificate
)
private
X509Certificate2
makeCertificateInternal
(
string
hostName
,
string
subjectName
,
{
DateTime
validFrom
,
DateTime
validTo
,
X509Certificate2
?
signingCertificate
)
if
(
signingCertificate
==
null
)
{
{
if
(
signingCertificate
==
null
)
return
generateCertificate
(
null
,
subjectName
,
subjectName
,
validFrom
,
validTo
);
{
}
return
generateCertificate
(
null
,
subjectName
,
subjectName
,
validFrom
,
validTo
);
}
var
kp
=
DotNetUtilities
.
GetKeyPair
(
signingCertificate
.
PrivateKey
);
return
generateCertificate
(
hostName
,
subjectName
,
signingCertificate
.
Subject
,
validFrom
,
validTo
,
var
kp
=
DotNetUtilities
.
GetKeyPair
(
signingCertificate
.
PrivateKey
);
issuerPrivateKey
:
kp
.
Private
);
return
generateCertificate
(
hostName
,
subjectName
,
signingCertificate
.
Subject
,
validFrom
,
validTo
,
}
issuerPrivateKey
:
kp
.
Private
);
}
/// <summary>
/// Makes the certificate internal.
/// <summary>
/// </summary>
/// Makes the certificate internal.
/// <param name="subject">The s subject cn.</param>
/// </summary>
/// <param name="switchToMtaIfNeeded">if set to <c>true</c> [switch to MTA if needed].</param>
/// <param name="subject">The s subject cn.</param>
/// <param name="signingCert">The signing cert.</param>
/// <param name="switchToMtaIfNeeded">if set to <c>true</c> [switch to MTA if needed].</param>
/// <returns>X509Certificate2.</returns>
/// <param name="signingCert">The signing cert.</param>
private
X509Certificate2
makeCertificateInternal
(
string
subject
,
/// <returns>X509Certificate2.</returns>
bool
switchToMtaIfNeeded
,
X509Certificate2
?
signingCert
=
null
)
private
X509Certificate2
makeCertificateInternal
(
string
subject
,
{
bool
switchToMtaIfNeeded
,
X509Certificate2
?
signingCert
=
null
)
return
makeCertificateInternal
(
subject
,
$"CN=
{
subject
}
"
,
{
DateTime
.
UtcNow
.
AddDays
(-
certificateGraceDays
),
DateTime
.
UtcNow
.
AddDays
(
certificateValidDays
),
return
makeCertificateInternal
(
subject
,
$"CN=
{
subject
}
"
,
signingCert
);
DateTime
.
UtcNow
.
AddDays
(-
certificateGraceDays
),
DateTime
.
UtcNow
.
AddDays
(
certificateValidDays
),
}
signingCert
);
}
}
}
}
}
src/Titanium.Web.Proxy/Certificates/BCCertificateMakerFast.cs
View file @
24c5332d
using
System
;
using
System
;
using
System.IO
;
using
System.IO
;
using
System.Net
;
using
System.Security.Cryptography.X509Certificates
;
using
System.Security.Cryptography.X509Certificates
;
using
Org.BouncyCastle.Asn1
;
using
Org.BouncyCastle.Asn1
;
using
Org.BouncyCastle.Asn1.Pkcs
;
using
Org.BouncyCastle.Asn1.Pkcs
;
...
@@ -99,7 +100,13 @@ namespace Titanium.Web.Proxy.Network.Certificate
...
@@ -99,7 +100,13 @@ namespace Titanium.Web.Proxy.Network.Certificate
if
(
hostName
!=
null
)
if
(
hostName
!=
null
)
{
{
// add subject alternative names
// add subject alternative names
var
subjectAlternativeNames
=
new
Asn1Encodable
[]
{
new
GeneralName
(
GeneralName
.
DnsName
,
hostName
)
};
var
nameType
=
GeneralName
.
DnsName
;
if
(
IPAddress
.
TryParse
(
hostName
,
out
_
))
{
nameType
=
GeneralName
.
IPAddress
;
}
var
subjectAlternativeNames
=
new
Asn1Encodable
[]
{
new
GeneralName
(
nameType
,
hostName
)
};
var
subjectAlternativeNamesExtension
=
new
DerSequence
(
subjectAlternativeNames
);
var
subjectAlternativeNamesExtension
=
new
DerSequence
(
subjectAlternativeNames
);
certificateGenerator
.
AddExtension
(
X509Extensions
.
SubjectAlternativeName
.
Id
,
false
,
certificateGenerator
.
AddExtension
(
X509Extensions
.
SubjectAlternativeName
.
Id
,
false
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment