Skip to content

Commit

Permalink
fix(handshake): Use RSA-PSS when signing nonces (#24)
Browse files Browse the repository at this point in the history
Counterpart on the server: relaycorp/relaynet-gateway-android#65
  • Loading branch information
gnarea authored Jul 28, 2020
1 parent 8768358 commit a645807
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 7 deletions.
7 changes: 7 additions & 0 deletions src/main/kotlin/tech/relaycorp/poweb/CryptoUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package tech.relaycorp.poweb

import org.bouncycastle.jce.provider.BouncyCastleProvider

object CryptoUtils {
val BC_PROVIDER = BouncyCastleProvider()
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder
import org.bouncycastle.operator.ContentSigner
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder
import tech.relaycorp.poweb.CryptoUtils
import tech.relaycorp.relaynet.wrappers.x509.Certificate
import java.security.PrivateKey

class NonceSigner(internal val certificate: Certificate, private val privateKey: PrivateKey) {
fun sign(nonce: ByteArray): ByteArray {
val signedDataGenerator = CMSSignedDataGenerator()

val signerBuilder = JcaContentSignerBuilder("SHA256withRSA")
val signerBuilder = JcaContentSignerBuilder("SHA256WITHRSAANDMGF1")
.setProvider(CryptoUtils.BC_PROVIDER)
val contentSigner: ContentSigner = signerBuilder.build(privateKey)
val signerInfoGenerator = JcaSignerInfoGeneratorBuilder(
JcaDigestCalculatorProviderBuilder()
Expand Down
9 changes: 6 additions & 3 deletions src/test/kotlin/tech/relaycorp/poweb/handshake/CMSUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import org.bouncycastle.cms.CMSSignedData
import org.bouncycastle.cms.SignerInformation
import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder
import org.bouncycastle.util.Selector
import tech.relaycorp.poweb.CryptoUtils
import tech.relaycorp.relaynet.wrappers.x509.Certificate

object CMSUtils {
Expand All @@ -20,16 +21,18 @@ object CMSUtils {

val signerInfo = getSignerInfoFromSignedData(signedData)

// We shouldn't have to force this type cast but this is the only way I could get the code to work and, based on
// what I found online, that's what others have had to do as well
// We shouldn't have to force this type cast but this is the only way I could get the code
// to work and, based on what I found online, that's what others have had to do as well
@Suppress("UNCHECKED_CAST") val signerCertSelector = X509CertificateHolderSelector(
signerInfo.sid.issuer,
signerInfo.sid.serialNumber
) as Selector<X509CertificateHolder>

val signerCertMatches = signedData.certificates.getMatches(signerCertSelector)
val signerCertificateHolder = signerCertMatches.first()
val verifier = JcaSimpleSignerInfoVerifierBuilder().build(signerCertificateHolder)
val verifier = JcaSimpleSignerInfoVerifierBuilder()
.setProvider(CryptoUtils.BC_PROVIDER)
.build(signerCertificateHolder)

signerInfo.verify(verifier)

Expand Down
20 changes: 17 additions & 3 deletions src/test/kotlin/tech/relaycorp/poweb/handshake/NonceSignerTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import org.bouncycastle.asn1.ASN1Primitive
import org.bouncycastle.asn1.DEROctetString
import org.bouncycastle.asn1.cms.Attribute
import org.bouncycastle.asn1.cms.ContentInfo
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers
import org.bouncycastle.cms.CMSSignedData
import org.bouncycastle.util.CollectionStore
import org.junit.jupiter.api.Nested
Expand Down Expand Up @@ -159,19 +161,31 @@ class NonceSignerTest {
assertEquals(certificate.certificateHolder, attachedCerts[0])
}

@Test
fun `Signature algorithm should be RSA-PSS`() {
val serialization = signer.sign(nonce)

val cmsSignedData = parseCmsSignedData(serialization)

val signerInfo = cmsSignedData.signerInfos.first()
assertEquals(PKCSObjectIdentifiers.id_RSASSA_PSS.id, signerInfo.encryptionAlgOID)
}

@Test
fun `SHA-256 should be used`() {
val serialization = signer.sign(nonce)

val cmsSignedData = parseCmsSignedData(serialization)

assertEquals(1, cmsSignedData.digestAlgorithmIDs.size)
val sha256Oid = ASN1ObjectIdentifier("2.16.840.1.101.3.4.2.1")
assertEquals(sha256Oid, cmsSignedData.digestAlgorithmIDs.first().algorithm)
assertEquals(
NISTObjectIdentifiers.id_sha256,
cmsSignedData.digestAlgorithmIDs.first().algorithm
)

val signerInfo = cmsSignedData.signerInfos.first()

assertEquals(sha256Oid, signerInfo.digestAlgorithmID.algorithm)
assertEquals(NISTObjectIdentifiers.id_sha256, signerInfo.digestAlgorithmID.algorithm)
}

@Test
Expand Down

0 comments on commit a645807

Please sign in to comment.