Commits

rimmington  committed d0707f7 Draft

removed HmacAlgorithm and subclasses in favor of re-using DigestAlgorithm

  • Participants
  • Parent commits f72eb7b

Comments (0)

Files changed (11)

File crypto/bouncycastle/ecdh.ceylon

 import org.bouncycastle.jcajce.provider.asymmetric.ec { BCECPublicKey, BCECPrivateKey, KeyFactorySpi { ECDHKeyFactory = ECDH } }
 
 import crypto.bouncycastle.primitives { ephemeralKeysFromSharedSecret, randomBytes }
-import crypto.spec { ECDH, EphemeralSharedPart, IncompleteEphemeralKey, EphemeralKeys, SymmetricEncryptionAlgorithm, HmacAlgorithm, nonceByteLength }
+import crypto.spec { ECDH, EphemeralSharedPart, IncompleteEphemeralKey, EphemeralKeys, SymmetricEncryptionAlgorithm, DigestAlgorithm, nonceByteLength }
 import crypto.spec.util { compareSequences, signedToUnsignedBytes }
 
 X9ECParameters x9prime192v1 = x962Curve("prime192v1");
                 EphemeralSharedPartImpl remoteSharedPart,
                 SymmetricEncryption symmetricEncryption, Hmac hmac)
                 given SymmetricEncryption satisfies SymmetricEncryptionAlgorithm
-                given Hmac satisfies HmacAlgorithm {
+                given Hmac satisfies DigestAlgorithm {
             value ka = keyAgreement("ECDH", "BC");
             ka.init(privateKey);
             ka.doPhase(remoteSharedPart.publicKey, true);

File crypto/bouncycastle/keygen.ceylon

 import org.bouncycastle.crypto.digests { WhirlpoolDigest }
 import org.bouncycastle.crypto.params { HKDFParameters }
 
-import crypto.spec { HmacWhirlpool, HKDF }
+import crypto.spec { Whirlpool, HKDF }
 
 shared object bouncyHkdf
-        satisfies HKDF<HmacWhirlpool> {
-    shared actual [Integer+] generate(HmacWhirlpool algorithm,
+        satisfies HKDF<Whirlpool> {
+    shared actual [Integer+] generate(Whirlpool algorithm,
             [Integer+] secret, [Integer+] nonce, [Integer+] info, Integer size) {
         assert(size > 0);
         value buf = newByteBuffer(size);

File crypto/bouncycastle/primitives/keygen.ceylon

-import crypto.spec { SymmetricEncryptionAlgorithm, HmacAlgorithm, EphemeralKeys, SharedKey, hmacWhirlpool }
+import crypto.spec { SymmetricEncryptionAlgorithm, DigestAlgorithm, EphemeralKeys, SharedKey, whirlpool }
 import crypto.spec.util { codepointsOf }
 import crypto.bouncycastle { bouncyHkdf }
 
 // (https://tools.ietf.org/html/rfc5996#section-2.13)
 shared EphemeralKeys<SymmetricEncryption, Hmac> ephemeralKeysFromSharedSecret<SymmetricEncryption, Hmac>(
         [Integer+] sharedSecret, [Integer+] sharedNonce,
-        SymmetricEncryption symmetricEncryption, Hmac hmac)
+        SymmetricEncryption symmetricEncryption, Hmac hmac,
+        Integer hmacKeySize = 256 / 8)
         given SymmetricEncryption satisfies SymmetricEncryptionAlgorithm
-        given Hmac satisfies HmacAlgorithm {
-    value concatenatedSize = symmetricEncryption.keySize + hmac.keySize;
+        given Hmac satisfies DigestAlgorithm {
+    value concatenatedSize = symmetricEncryption.keySize + hmacKeySize;
     assert(nonempty info = codepointsOf("EphemeralKey").sequence);
-    value keyMaterial = bouncyHkdf.generate(hmacWhirlpool, sharedSecret,
+    value keyMaterial = bouncyHkdf.generate(whirlpool, sharedSecret,
         sharedNonce, info, concatenatedSize);
     
     assert(nonempty encryptionKeyMaterial = keyMaterial.segment(
     value encryptionKey = SharedKey(encryptionKeyMaterial, symmetricEncryption);
     
     assert(nonempty hmacKeyMaterial = keyMaterial.segment(
-        symmetricEncryption.keySize, hmac.keySize));
+        symmetricEncryption.keySize, hmacKeySize));
     value hmacKey = SharedKey(hmacKeyMaterial, hmac);
 
     return EphemeralKeys(encryptionKey, hmacKey);

File crypto/bouncycastle/test/run.ceylon

 
 import org.bouncycastle.jce.provider { BouncyCastleProvider }
 
-import crypto.spec { aes256Ofb, hmacSha1 }
+import crypto.spec { aes256Ofb, sha1 }
 import crypto.bouncycastle { bouncyEcdh }
 
 "Run the tests for the module `crypto.bouncycastle`"
     assert(bouncyEcdh.decodeSharedPart(aliceShared.asBytes) == aliceShared);
     
     value bob = bouncyEcdh.randomIncompleteEphemeralKey();
-    value aliceSecret = alice.complete(bob.sharedPart, aes256Ofb, hmacSha1);
-    value bobSecret = bob.complete(alice.sharedPart, aes256Ofb, hmacSha1);
+    value aliceSecret = alice.complete(bob.sharedPart, aes256Ofb, sha1);
+    value bobSecret = bob.complete(alice.sharedPart, aes256Ofb, sha1);
     
     assert(aliceSecret == bobSecret);
 }

File crypto/spec/algorithms.ceylon

         satisfies NamedAlgorithm {
     "The size of the digest in bytes."
     shared formal Integer size;
+    shared formal ObjectIdentifier hmacIdentifier;
 }
 
 shared abstract class Sha1()
         satisfies DigestAlgorithm {
     shared actual ObjectIdentifier identifier => nothing;
     shared actual Integer size = 20;
+    shared actual ObjectIdentifier hmacIdentifier =
+        ObjectIdentifier([2, 16, 840, 113549, 2, 7]);
 }
 
 shared object sha1 extends Sha1() {}
         satisfies DigestAlgorithm {
     shared actual ObjectIdentifier identifier => nothing;
     shared actual Integer size = 64;
+    shared actual ObjectIdentifier hmacIdentifier => nothing;
 }
 
-shared object whirlpool extends Whirlpool() {}
-
-shared interface HmacAlgorithm
-        satisfies NamedAlgorithm {
-    shared formal DigestAlgorithm digestAlgorithm;
-    // TODO: check validity
-    "The size of the key in bytes."
-    shared formal Integer keySize;
-}
-
-shared abstract class HmacSha1()
-        of hmacSha1
-        satisfies HmacAlgorithm {
-    shared actual DigestAlgorithm digestAlgorithm = sha1;
-    // TODO: check HmacSha1 key byte size
-    shared actual Integer keySize = 256 / 8;
-    shared actual ObjectIdentifier identifier =
-        ObjectIdentifier([2, 16, 840, 113549, 2, 7]);
-}
-
-shared object hmacSha1 extends HmacSha1() {}
-
-shared abstract class HmacWhirlpool()
-        of hmacWhirlpool
-        satisfies HmacAlgorithm {
-    shared actual DigestAlgorithm digestAlgorithm = whirlpool;
-    shared actual Integer keySize = 256 / 8;
-    shared actual ObjectIdentifier identifier => nothing;
-}
-
-shared object hmacWhirlpool extends HmacWhirlpool() {}
+shared object whirlpool extends Whirlpool() {}

File crypto/spec/ecdh.ceylon

     shared formal EphemeralKeys<SymmetricEncryption, Hmac> complete<SymmetricEncryption, Hmac>(
         EphemeralSharedPartImpl remoteSharedPart, SymmetricEncryption symmetricEncryption, Hmac hmac)
         given SymmetricEncryption satisfies SymmetricEncryptionAlgorithm 
-        given Hmac satisfies HmacAlgorithm;
+        given Hmac satisfies DigestAlgorithm;
 }

File crypto/spec/keygen.ceylon

 shared interface HKDF<SupportedAlgorithms>
-        given SupportedAlgorithms satisfies HmacAlgorithm {
+        given SupportedAlgorithms satisfies DigestAlgorithm {
     shared formal [Integer+] generate(SupportedAlgorithms algorithm,
     [Integer+] secret, [Integer+] nonce, [Integer+] info, Integer size);
 }

File crypto/spec/keys.ceylon

 
 shared class EphemeralKeys<out SymmetricEncryption, out Hmac>(encryptionKey, hmacKey)
         given SymmetricEncryption satisfies SymmetricEncryptionAlgorithm 
-        given Hmac satisfies HmacAlgorithm {
+        given Hmac satisfies DigestAlgorithm {
     shared SharedKey<SymmetricEncryption> encryptionKey;
     shared SharedKey<Hmac> hmacKey;
     

File crypto/test/bouncy.ceylon

 
 import org.bouncycastle.jce.provider { BouncyCastleProvider }
 
-import crypto.spec { aes256Ofb, hmacSha1, Aes256Ofb, HmacSha1, EphemeralKeys, SharedKey }
+import crypto.spec { aes256Ofb, sha1, Aes256Ofb, Sha1, EphemeralKeys, SharedKey }
 import crypto.spec.util { codepointsOf, asCodepoints }
 import crypto.bouncycastle { bouncyEcdh }
 import crypto.toy { toyEcdh }
     //aes(keys.encryptionKey);
 }
 
-EphemeralKeys<Aes256Ofb, HmacSha1> interop() {
+EphemeralKeys<Aes256Ofb, Sha1> interop() {
     value toyKey = toyEcdh.randomIncompleteEphemeralKey();
     value bouncyKey = bouncyEcdh.randomIncompleteEphemeralKey();
     
     value bouncyForToy = toyEcdh.decodeSharedPart(bouncyShared);
     value toyForBouncy = bouncyEcdh.decodeSharedPart(toyShared);
     
-    value toySecret = toyKey.complete(bouncyForToy, aes256Ofb, hmacSha1);
-    value bouncySecret = bouncyKey.complete(toyForBouncy, aes256Ofb, hmacSha1);
+    value toySecret = toyKey.complete(bouncyForToy, aes256Ofb, sha1);
+    value bouncySecret = bouncyKey.complete(toyForBouncy, aes256Ofb, sha1);
     
     assert(toySecret == bouncySecret);
     

File crypto/toy/ecdh.ceylon

 import ceylon.math.whole { Whole }
 
 import crypto.bouncycastle.primitives { randomBytes, ephemeralKeysFromSharedSecret }
-import crypto.spec { EphemeralKeys, SymmetricEncryptionAlgorithm, HmacAlgorithm, ECDH, EphemeralSharedPart, IncompleteEphemeralKey, nonceByteLength }
+import crypto.spec { EphemeralKeys, SymmetricEncryptionAlgorithm, DigestAlgorithm, ECDH, EphemeralSharedPart, IncompleteEphemeralKey, nonceByteLength }
 import crypto.spec.math { Point, Domain }
 import crypto.spec.asn1 { ECPublicKeyInfo, asn1ECPublicKeyInfo, ASN1Sequence, asn1Decodable, OctetString, ASN1Representable }
 import crypto.spec.util { compareSequences }
         shared actual EphemeralKeys<SymmetricEncryption, Hmac> complete<SymmetricEncryption, Hmac>(
                 ToyEphemeralSharedPart remoteSharedPart, SymmetricEncryption symmetricEncryption, Hmac hmac)
                 given SymmetricEncryption satisfies SymmetricEncryptionAlgorithm 
-                given Hmac satisfies HmacAlgorithm {
+                given Hmac satisfies DigestAlgorithm {
             assert(remoteSharedPart.domain == sharedPart.domain);
             assert(remoteSharedPart.nonce.size == nonceByteLength);
             value sharedSecret = combineToSharedSecret(sharedPart.domain, d,

File crypto/toy/test/root.ceylon

-import crypto.spec { Aes256Ofb, HmacSha1, EphemeralKeys, aes256Ofb, hmacSha1 }
+import crypto.spec { Aes256Ofb, Sha1, EphemeralKeys, aes256Ofb, sha1 }
 
 import crypto.toy { toyEcdh }
 
     encodeSharedPart();
 }
 
-EphemeralKeys<Aes256Ofb, HmacSha1> ecdh() {
+EphemeralKeys<Aes256Ofb, Sha1> ecdh() {
     value alice = toyEcdh.randomIncompleteEphemeralKey();
     value bob = toyEcdh.randomIncompleteEphemeralKey();
     
-    value aliceSecret = alice.complete(bob.sharedPart, aes256Ofb, hmacSha1);
-    value bobSecret = bob.complete(alice.sharedPart, aes256Ofb, hmacSha1);
+    value aliceSecret = alice.complete(bob.sharedPart, aes256Ofb, sha1);
+    value bobSecret = bob.complete(alice.sharedPart, aes256Ofb, sha1);
     assert(aliceSecret == bobSecret);
     
     return aliceSecret;