Exemple #1
0
    def _has_EC_support(self):
        has_ec_support = True
        # U2F needs OpenSSL 1.0.0 or higher
        # The EC OpenSSL API calls made by M2Crypto don't work with OpenSSl 0.9.8!
        version_text = m2.OPENSSL_VERSION_TEXT
        match = re.match(r"OpenSSL (?P<version>\d\.\d\.\d)", version_text)
        if match is None:
            # Fail on unknown OpenSSL version string format
            self.fail(
                "Could not detect OpenSSL version - unknown version string format: '%s'"
                % version_text)
        else:
            if match.group('version')[0] == '0':
                has_ec_support = False

        # The following command needs support for ECDSA in openssl!
        # Since Red Hat systems (including Fedora) use an openssl version without
        # support for the NIST P-256 elliptic curve (as of March 2015),
        # this command will fail with a NULL pointer exception on these systems
        try:
            EC.load_key_bio(BIO.MemoryBuffer(self.ATTESTATION_PRIVATE_KEY_PEM))
        except ValueError:
            has_ec_support = False

        return has_ec_support
Exemple #2
0
    def test_u2f_unsupported_openssl_missing_curve(self):
        """
        Try registration with an OpenSSL missing the NIST P-256 curve and check the error messages
        """
        skip_test = True

        # Only allow OpenSSL >=1.0.0 with missing EC support
        version_text = m2.OPENSSL_VERSION_TEXT
        match = re.match(r"OpenSSL (?P<version>\d\.\d\.\d)", version_text)
        if match is None:
            # Fail on unknown OpenSSL version string format
            self.fail("Could not detect OpenSSL version - unknown version string format: '%s'" % version_text)
        else:
            if match.group("version")[0] != "0":
                # Only run test on missing NIST P-256 curve support
                try:
                    EC.load_key_bio(BIO.MemoryBuffer(self.ATTESTATION_PRIVATE_KEY_PEM))
                except ValueError:
                    skip_test = False

        if skip_test:
            self.skipTest("This test can only be run with OpenSSL missing the " "NIST P-256 curve!")

        # Initial token registration step
        response_registration1_JSON = self._registration1()
        self.assertTrue('"value": true' in response_registration1_JSON, "Response: %r" % response_registration1_JSON)
        self.assertTrue('"challenge":' in response_registration1_JSON, "Response: %r" % response_registration1_JSON)
        self.assertTrue('"serial":' in response_registration1_JSON, "Response: %r" % response_registration1_JSON)

        response_registration1 = json.loads(response_registration1_JSON.body)
        challenge_registration = response_registration1.get("detail", {}).get("challenge")
        self.serial = response_registration1.get("detail", {}).get("serial")
        self.serials.add(self.serial)

        client_data_registration = self._createClientDataObject("registration", challenge_registration)
        # Since we have no supported OpenSSL version to calculate the registration response
        # we use a hard-coded correctly-formed fake registration response
        registration_response = binascii.unhexlify(self.FAKE_REGISTRATION_DATA_HEX)
        registration_response_message = {
            "registrationData": base64.urlsafe_b64encode(registration_response),
            "clientData": base64.urlsafe_b64encode(client_data_registration),
        }

        # Complete the token registration
        response_registration2_JSON = self._registration2(json.dumps(registration_response_message))

        # Registration must fail
        self.assertTrue('"status": false' in response_registration2_JSON, "Response: %r" % response_registration2_JSON)

        # Check for correct error messages
        self.assertTrue(
            "missing ECDSA support for the NIST P-256 curve in OpenSSL" in response_registration2_JSON,
            "Response: %r" % response_registration2_JSON,
        )
Exemple #3
0
    def ec_from_private_pem(pem, password=None):
        "Get the EC from a private PEM."

        def get_password(*args):
            return password or ""

        return EC.load_key_bio(BIO.MemoryBuffer(pem), get_password)
Exemple #4
0
    def key_from_pem(self, pem):
        "Get the EC from a public/private keypair stored in the PEM."

        def get_password(*args):
            return ""

        return EC.load_key_bio(BIO.MemoryBuffer(pem), get_password)
Exemple #5
0
    def _register(self, data):
        client_param = data[:32]
        app_param = data[32:]

        # ECC key generation
        privu = EC.gen_params(CURVE)
        privu.gen_key()
        pub_key = str(privu.pub().get_der())[-65:]

        # Store
        key_handle = os.urandom(64)
        bio = BIO.MemoryBuffer()
        privu.save_key_bio(bio, None)
        self.data['keys'][key_handle.encode('hex')] = {
            'priv_key': bio.read_all(),
            'app_param': app_param.encode('hex')
        }
        self._persist()

        # Attestation signature
        cert_priv = EC.load_key_bio(BIO.MemoryBuffer(CERT_PRIV))
        cert = CERT
        digest = H(chr(0x00) + app_param + client_param + key_handle + pub_key)
        signature = cert_priv.sign_dsa_asn1(digest)

        raw_response = chr(0x05) + pub_key + chr(len(key_handle)) + \
            key_handle + cert + signature

        return raw_response
Exemple #6
0
    def _authenticate(self, data):
        client_param = data[:32]
        app_param = data[32:64]
        kh_len = ord(data[64])
        key_handle = data[65:65 + kh_len].encode('hex')
        if key_handle not in self.data['keys']:
            raise ValueError("Unknown key handle!")

        # Unwrap:
        unwrapped = self.data['keys'][key_handle]
        if app_param != unwrapped['app_param'].decode('hex'):
            raise ValueError("Incorrect app param!")
        priv_pem = unwrapped['priv_key'].encode('ascii')
        privu = EC.load_key_bio(BIO.MemoryBuffer(priv_pem))

        # Increment counter
        self.data['counter'] += 1
        self._persist()

        # Create signature
        touch = chr(1)  # Always indicate user presence
        counter = struct.pack('>I', self.data['counter'])

        digest = H(app_param + touch + counter + client_param)
        signature = privu.sign_dsa_asn1(digest)
        raw_response = touch + counter + signature

        return raw_response
Exemple #7
0
def load_key(pem):
    """ PEM形式のECプライベートキーを読み込みます """
    from M2Crypto import EC, BIO

    bio = BIO.IOBuffer(BIO.MemoryBuffer(pem))
    key = EC.load_key_bio(bio)
    return key
Exemple #8
0
    def _createRegistrationResponseMessage(self,
                                           client_data,
                                           key_set=None,
                                           correct=True
                                           ):
        """
        Create a registration response message according to the FIDO U2F specification
        """
        if not key_set:
            raise ValueError("Unknown key number requested!")
        (key_handle_hex, ecc_key) = key_set

        #
        # Create the registration_data object
        #
        registration_data = chr(0x05)  # First byte must be 0x05

        # The public key length is set to a fixed length of 65 characters in the U2F specification
        public_key = str(ecc_key.pub().get_der())[-65:]
        registration_data += public_key

        key_handle = binascii.unhexlify(key_handle_hex)
        registration_data += chr(len(key_handle))
        registration_data += key_handle

        attestation_cert_der = binascii.unhexlify(self.ATTESTATION_CERT_HEX)
        registration_data += attestation_cert_der

        # Create the ECDSA signature
        digest = sha256()
        digest.update(chr(0x00) +
                      sha256(self.origin).digest() +
                      sha256(client_data).digest() +
                      key_handle +
                      public_key
                      )

        cert_private_key = EC.load_key_bio(BIO.MemoryBuffer(self.ATTESTATION_PRIVATE_KEY_PEM))
        signature = cert_private_key.sign_dsa_asn1(digest.digest())

        if correct is False:
            # Change the signature to create an invalid registration response
            signature = signature[:-1]

        registration_data += signature

        #
        # Create the registration_response
        #
        registration_response = {
            'registrationData': base64.urlsafe_b64encode(registration_data),
            'clientData': base64.urlsafe_b64encode(client_data)
        }

        return json.dumps(registration_response)
Exemple #9
0
    def _createRegistrationResponseMessage(self,
                                           client_data,
                                           key_set=None,
                                           correct=True
                                           ):
        """
        Create a registration response message according to the FIDO U2F specification
        """
        if not key_set:
            raise ValueError("Unknown key number requested!")
        (key_handle_hex, ecc_key) = key_set

        #
        # Create the registration_data object
        #
        registration_data = chr(0x05)  # First byte must be 0x05

        # The public key length is set to a fixed length of 65 characters in the U2F specification
        public_key = str(ecc_key.pub().get_der())[-65:]
        registration_data += public_key

        key_handle = binascii.unhexlify(key_handle_hex)
        registration_data += chr(len(key_handle))
        registration_data += key_handle

        attestation_cert_der = binascii.unhexlify(self.ATTESTATION_CERT_HEX)
        registration_data += attestation_cert_der

        # Create the ECDSA signature
        digest = sha256()
        digest.update(chr(0x00) +
                      sha256(self.origin).digest() +
                      sha256(client_data).digest() +
                      key_handle +
                      public_key
                      )

        cert_private_key = EC.load_key_bio(BIO.MemoryBuffer(self.ATTESTATION_PRIVATE_KEY_PEM))
        signature = cert_private_key.sign_dsa_asn1(digest.digest())

        if correct is False:
            # Change the signature to create an invalid registration response
            signature = signature[:-1]

        registration_data += signature

        #
        # Create the registration_response
        #
        registration_response = {
            'registrationData': base64.urlsafe_b64encode(registration_data),
            'clientData': base64.urlsafe_b64encode(client_data)
        }

        return json.dumps(registration_response)
Exemple #10
0
    def _constructEcFromRawKeys(self, rawPrivateKey, rawPublicKey):
        assert(len(rawPrivateKey) == 32)
        assert(len(rawPublicKey) == 64)
        bytes1 = a2b_hex("02010104")
        bytes2 = a2b_hex("a00a06082a8648ce3d030107a14403420004")
        rawPrivateKey = toAsn1IntBytes(rawPrivateKey)
        b = bytes1 + asn1Length(len(rawPrivateKey)) + rawPrivateKey +\
            bytes2 + rawPublicKey
        b = bytearray([0x30]) + asn1Length(len(b)) + b
        pemPrivKeyBytes = PEMEncoder(b).getEncoded("EC PRIVATE KEY")

        return EC.load_key_bio(BIO.MemoryBuffer(pemPrivKeyBytes))
Exemple #11
0
    def _constructEcFromRawKeys(self, rawPrivateKey, rawPublicKey):
        assert (len(rawPrivateKey) == 32)
        assert (len(rawPublicKey) == 64)
        bytes1 = a2b_hex("02010104")
        bytes2 = a2b_hex("a00a06082a8648ce3d030107a14403420004")
        rawPrivateKey = toAsn1IntBytes(rawPrivateKey)
        b = bytes1 + asn1Length(len(rawPrivateKey)) + rawPrivateKey +\
            bytes2 + rawPublicKey
        b = bytearray([0x30]) + asn1Length(len(b)) + b
        pemPrivKeyBytes = PEMEncoder(b).getEncoded("EC PRIVATE KEY")

        return EC.load_key_bio(BIO.MemoryBuffer(pemPrivKeyBytes))
Exemple #12
0
    def _has_EC_support(self):
        has_ec_support = True
        # U2F needs OpenSSL 1.0.0 or higher
        # The EC OpenSSL API calls made by M2Crypto don't work with OpenSSl 0.9.8!
        version_text = m2.OPENSSL_VERSION_TEXT
        match = re.match(r"OpenSSL (?P<version>\d\.\d\.\d)", version_text)
        if match is None:
            # Fail on unknown OpenSSL version string format
            self.fail("Could not detect OpenSSL version - unknown version string format: '%s'" % version_text)
        else:
            if match.group("version")[0] == "0":
                has_ec_support = False

        # The following command needs support for ECDSA in openssl!
        # Since Red Hat systems (including Fedora) use an openssl version without
        # support for the NIST P-256 elliptic curve (as of March 2015),
        # this command will fail with a NULL pointer exception on these systems
        try:
            EC.load_key_bio(BIO.MemoryBuffer(self.ATTESTATION_PRIVATE_KEY_PEM))
        except ValueError:
            has_ec_support = False

        return has_ec_support
    def register(
        self,
        data,
        facet="https://www.example.com",
    ):
        """
        data = {
            "version": "U2F_V2",
            "challenge": string, //b64 encoded challenge
            "appId": string, //app_id
        }
        """
        if isinstance(data, basestring):
            data = json.loads(data)

        if data['version'] != "U2F_V2":
            raise ValueError("Unsupported U2F version: %s" % data['version'])

        # Client data
        client_data = {
            'typ': "navigator.id.finishEnrollment",
            'challenge': data['challenge'],
            'origin': facet
        }
        client_data = json.dumps(client_data)
        client_param = H(client_data)

        # ECC key generation
        privu = EC.gen_params(CURVE)
        privu.gen_key()
        pub_key = str(privu.pub().get_der())[-65:]

        # Store
        key_handle = rand_bytes(64)
        app_param = H(data['appId'])
        self.keys[key_handle] = (privu, app_param)

        # Attestation signature
        cert_priv = EC.load_key_bio(BIO.MemoryBuffer(CERT_PRIV))
        cert = CERT
        digest = H(chr(0x00) + app_param + client_param + key_handle + pub_key)
        signature = cert_priv.sign_dsa_asn1(digest)

        raw_response = chr(0x05) + pub_key + chr(len(key_handle)) + \
            key_handle + cert + signature

        return json.dumps({
            "registrationData": websafe_encode(raw_response),
            "clientData": websafe_encode(client_data),
        })
Exemple #14
0
    def __init__(self, curve=None, keystring=None, filename=None):
        if curve:
            self.ec = EC.gen_params(curve)
            self.ec.gen_key()

        elif keystring:
            self.ec = self.key_from_pem(
                "-----BEGIN EC PRIVATE KEY-----\n%s-----END EC PRIVATE KEY-----\n"
                % keystring.encode("BASE64"))

        elif filename:
            # this workaround is needed to run Tribler on Windows 64 bit
            membuf = BIO.MemoryBuffer(open(filename, 'rb').read())
            self.ec = EC.load_key_bio(membuf)
            membuf.close()
    def register(self, data, facet="https://www.example.com", ):
        """
        data = {
            "version": "U2F_V2",
            "challenge": string, //b64 encoded challenge
            "appId": string, //app_id
        }
        """
        if isinstance(data, basestring):
            data = json.loads(data)

        if data['version'] != "U2F_V2":
            raise ValueError("Unsupported U2F version: %s" % data['version'])

        # Client data
        client_data = {
            'typ': "navigator.id.finishEnrollment",
            'challenge': data['challenge'],
            'origin': facet
        }
        client_data = json.dumps(client_data)
        client_param = H(client_data)

        # ECC key generation
        privu = EC.gen_params(CURVE)
        privu.gen_key()
        pub_key = str(privu.pub().get_der())[-65:]

        # Store
        key_handle = rand_bytes(64)
        app_param = H(data['appId'])
        self.keys[key_handle] = (privu, app_param)

        # Attestation signature
        cert_priv = EC.load_key_bio(BIO.MemoryBuffer(CERT_PRIV))
        cert = CERT
        digest = H(chr(0x00) + app_param + client_param + key_handle + pub_key)
        signature = cert_priv.sign_dsa_asn1(digest)

        raw_response = chr(0x05) + pub_key + chr(len(key_handle)) + \
            key_handle + cert + signature

        return json.dumps({
            "registrationData": websafe_encode(raw_response),
            "clientData": websafe_encode(client_data),
        })
    def register(self, request, facet="https://www.example.com"):
        """
        RegisterRequest = {
            "version": "U2F_V2",
            "challenge": string, //b64 encoded challenge
            "appId": string, //app_id
        }
        """
        if not isinstance(request, RegisterRequest):
            request = RegisterRequest(request)

        if request.version != "U2F_V2":
            raise ValueError("Unsupported U2F version: %s" % request.version)

        # Client data
        client_data = ClientData(
            typ='navigator.id.finishEnrollment',
            challenge=request['challenge'],
            origin=facet
        )
        client_data = client_data.json
        client_param = H(client_data)

        # ECC key generation
        privu = EC.gen_params(CURVE)
        privu.gen_key()
        pub_key = str(privu.pub().get_der())[-65:]

        # Store
        key_handle = rand_bytes(64)
        app_param = request.appParam
        self.keys[key_handle] = (privu, app_param)

        # Attestation signature
        cert_priv = EC.load_key_bio(BIO.MemoryBuffer(CERT_PRIV))
        cert = CERT
        digest = H(chr(0x00) + app_param + client_param + key_handle + pub_key)
        signature = cert_priv.sign_dsa_asn1(digest)

        raw_response = chr(0x05) + pub_key + chr(len(key_handle)) + \
            key_handle + cert + signature

        return RegisterResponse(
            registrationData=websafe_encode(raw_response),
            clientData=websafe_encode(client_data),
        )
Exemple #17
0
    def register(self, request, facet="https://www.example.com"):
        """
        RegisterRequest = {
            "version": "U2F_V2",
            "challenge": string, //b64 encoded challenge
            "appId": string, //app_id
        }
        """

        if not isinstance(request, RegisterRequest):
            request = RegisterRequest(request)

        if request.version != "U2F_V2":
            raise ValueError("Unsupported U2F version: %s" % request.version)

        # Client data
        client_data = ClientData(typ='navigator.id.finishEnrollment',
                                 challenge=request['challenge'],
                                 origin=facet)
        client_data = client_data.json
        client_param = H(client_data)

        # ECC key generation
        privu = EC.gen_params(CURVE)
        privu.gen_key()
        pub_key = str(privu.pub().get_der())[-65:]

        # Store
        key_handle = rand_bytes(64)
        app_param = request.appParam
        self.keys[key_handle] = (privu, app_param)

        # Attestation signature
        cert_priv = EC.load_key_bio(BIO.MemoryBuffer(CERT_PRIV))
        cert = CERT
        digest = H(chr(0x00) + app_param + client_param + key_handle + pub_key)
        signature = cert_priv.sign_dsa_asn1(digest)

        raw_response = chr(0x05) + pub_key + chr(len(key_handle)) + \
            key_handle + cert + signature

        return RegisterResponse(
            registrationData=websafe_encode(raw_response),
            clientData=websafe_encode(client_data),
        )
Exemple #18
0
 def ec_from_private_pem(pem, password=None):
     "Get the EC from a private PEM."
     def get_password(*args):
         return password or ""
     return EC.load_key_bio(BIO.MemoryBuffer(pem), get_password)
Exemple #19
0
    def test_u2f_unsupported_openssl_missing_curve(self):
        """
        Try registration with an OpenSSL missing the NIST P-256 curve and check the error messages
        """
        skip_test = True

        # Only allow OpenSSL >=1.0.0 with missing EC support
        version_text = m2.OPENSSL_VERSION_TEXT
        match = re.match(r"OpenSSL (?P<version>\d\.\d\.\d)", version_text)
        if match is None:
            # Fail on unknown OpenSSL version string format
            self.fail(
                "Could not detect OpenSSL version - unknown version string format: '%s'"
                % version_text)
        else:
            if match.group('version')[0] != '0':
                # Only run test on missing NIST P-256 curve support
                try:
                    EC.load_key_bio(
                        BIO.MemoryBuffer(self.ATTESTATION_PRIVATE_KEY_PEM))
                except ValueError:
                    skip_test = False

        if skip_test:
            self.skipTest("This test can only be run with OpenSSL missing the "
                          "NIST P-256 curve!")

        # Initial token registration step
        response_registration1 = self.get_json_body(self._registration1())

        # check for status and value
        self.assertIn('result', response_registration1,
                      "Response: %r" % response_registration1)
        self.assertIn('status', response_registration1['result'],
                      "Response: %r" % response_registration1)
        self.assertTrue(response_registration1['result']['status'])
        self.assertIn('value', response_registration1['result'],
                      "Response: %r" % response_registration1)
        self.assertTrue(response_registration1['result']['value'])

        # check detail object containing serial and registerrequest
        self.assertIn('detail', response_registration1,
                      "Response: %r" % response_registration1)

        # check for correct serial
        self.assertIn('serial', response_registration1['detail'],
                      "Response: %r" % response_registration1)
        self.assertEqual(response_registration1['detail']['serial'][:3], "U2F")

        # check for correct registerrequest object
        self.assertIn('registerrequest', response_registration1['detail'],
                      "Response: %r" % response_registration1)
        self.assertIn('challenge',
                      response_registration1['detail']['registerrequest'],
                      "Response: %r" % response_registration1)
        # check for non-empty and correctly-padded challenge
        self.assertNotEqual(
            response_registration1['detail']['registerrequest']['challenge'],
            '')
        self.assertEqual(
            len(response_registration1['detail']['registerrequest']
                ['challenge']) % 4, 0)
        self.assertIn('version',
                      response_registration1['detail']['registerrequest'],
                      "Response: %r" % response_registration1)
        # only U2F_V2 is supported right now
        self.assertEqual(
            response_registration1['detail']['registerrequest']['version'],
            "U2F_V2")
        self.assertIn('appId',
                      response_registration1['detail']['registerrequest'],
                      "Response: %r" % response_registration1)
        self.assertEqual(
            response_registration1['detail']['registerrequest']['appId'],
            self.origin)

        challenge_registration = response_registration1['detail'][
            'registerrequest']['challenge']
        self.serial = response_registration1['detail']['serial']
        self.serials.add(self.serial)

        client_data_registration = self._createClientDataObject(
            'registration',
            challenge_registration,
        )
        # Since we have no supported OpenSSL version to calculate the registration response
        # we use a hard-coded correctly-formed fake registration response
        registration_response = binascii.unhexlify(
            self.FAKE_REGISTRATION_DATA_HEX)
        registration_response_message = {
            'registrationData':
            base64.urlsafe_b64encode(registration_response),
            'clientData': base64.urlsafe_b64encode(client_data_registration)
        }

        # Complete the token registration
        response_registration2 = self.get_json_body(
            self._registration2(json.dumps(registration_response_message)))

        # Registration must fail
        # check for status and value
        self.assertIn('result', response_registration2,
                      "Response: %r" % response_registration2)
        self.assertIn('status', response_registration2['result'],
                      "Response: %r" % response_registration2)
        self.assertFalse(response_registration2['result']['status'])
        # check explicitly, that no "value: true" is responded
        if 'value' in response_registration2['result']:
            self.assertFalse(response_registration2['result']['value'])

        # Check for correct error messages
        self.assertIn('error', response_registration2['result'],
                      "Response: %r" % response_registration2)
        self.assertIn('message', response_registration2['result']['error'],
                      "Response: %r" % response_registration2)
        self.assertIn(
            "missing ECDSA support for the NIST P-256 curve in OpenSSL",
            response_registration2['result']['error']['message'])
Exemple #20
0
    def test_u2f_unsupported_openssl_missing_curve(self):
        """
        Try registration with an OpenSSL missing the NIST P-256 curve and check the error messages
        """
        skip_test = True

        # Only allow OpenSSL >=1.0.0 with missing EC support
        version_text = m2.OPENSSL_VERSION_TEXT
        match = re.match(r"OpenSSL (?P<version>\d\.\d\.\d)", version_text)
        if match is None:
            # Fail on unknown OpenSSL version string format
            self.fail("Could not detect OpenSSL version - unknown version string format: '%s'"
                      % version_text)
        else:
            if match.group('version')[0] != '0':
                # Only run test on missing NIST P-256 curve support
                try:
                    EC.load_key_bio(BIO.MemoryBuffer(self.ATTESTATION_PRIVATE_KEY_PEM))
                except ValueError:
                    skip_test = False

        if skip_test:
            self.skipTest(
                "This test can only be run with OpenSSL missing the "
                "NIST P-256 curve!"
                )

        # Initial token registration step
        response_registration1 = self.get_json_body(self._registration1())

        # check for status and value
        self.assertIn('result', response_registration1,
                      "Response: %r" % response_registration1)
        self.assertIn('status', response_registration1['result'],
                      "Response: %r" % response_registration1)
        self.assertTrue(response_registration1['result']['status'])
        self.assertIn('value', response_registration1['result'],
                      "Response: %r" % response_registration1)
        self.assertTrue(response_registration1['result']['value'])

        # check detail object containing serial and registerrequest
        self.assertIn('detail', response_registration1,
                      "Response: %r" % response_registration1)

        # check for correct serial
        self.assertIn('serial', response_registration1['detail'],
                      "Response: %r" % response_registration1)
        self.assertEqual(response_registration1['detail']['serial'][:3], "U2F")

        # check for correct registerrequest object
        self.assertIn('registerrequest', response_registration1['detail'],
                      "Response: %r" % response_registration1)
        self.assertIn('challenge', response_registration1['detail']['registerrequest'],
                      "Response: %r" % response_registration1)
        # check for non-empty and correctly-padded challenge
        self.assertNotEqual(response_registration1['detail']['registerrequest']['challenge'], '')
        self.assertEqual(len(response_registration1['detail']['registerrequest']['challenge']) % 4,
                         0)
        self.assertIn('version', response_registration1['detail']['registerrequest'],
                      "Response: %r" % response_registration1)
        # only U2F_V2 is supported right now
        self.assertEqual(response_registration1['detail']['registerrequest']['version'], "U2F_V2")
        self.assertIn('appId', response_registration1['detail']['registerrequest'],
                      "Response: %r" % response_registration1)
        self.assertEqual(response_registration1['detail']['registerrequest']['appId'], self.origin)

        challenge_registration = response_registration1['detail']['registerrequest']['challenge']
        self.serial = response_registration1['detail']['serial']
        self.serials.add(self.serial)

        client_data_registration = self._createClientDataObject('registration',
                                                                challenge_registration,
                                                                )
        # Since we have no supported OpenSSL version to calculate the registration response
        # we use a hard-coded correctly-formed fake registration response
        registration_response = binascii.unhexlify(self.FAKE_REGISTRATION_DATA_HEX)
        registration_response_message = {
            'registrationData': base64.urlsafe_b64encode(registration_response),
            'clientData': base64.urlsafe_b64encode(client_data_registration)
        }

        # Complete the token registration
        response_registration2 = self.get_json_body(
            self._registration2(json.dumps(registration_response_message))
            )

        # Registration must fail
        # check for status and value
        self.assertIn('result', response_registration2,
                      "Response: %r" % response_registration2)
        self.assertIn('status', response_registration2['result'],
                      "Response: %r" % response_registration2)
        self.assertFalse(response_registration2['result']['status'])
        # check explicitly, that no "value: true" is responded
        if 'value' in response_registration2['result']:
            self.assertFalse(response_registration2['result']['value'])

        # Check for correct error messages
        self.assertIn('error', response_registration2['result'],
                      "Response: %r" % response_registration2)
        self.assertIn('message', response_registration2['result']['error'],
                      "Response: %r" % response_registration2)
        self.assertIn("missing ECDSA support for the NIST P-256 curve in OpenSSL",
                      response_registration2['result']['error']['message'])
Exemple #21
0
 def from_PEM(self, pemkey):
     """import a EC key from a PEM encoded string"""
     m = BIO.MemoryBuffer(pemkey)
     self._key = EC.load_key_bio(m)
Exemple #22
0
def read_keypair(keypairfilename):
    membuf = BIO.MemoryBuffer(open(keypairfilename, 'rb').read())
    key = EC.load_key_bio(membuf)
    membuf.close()
    return key
Exemple #23
0
         else:
             j = privatekey
         if j['type'] != 'EC_Private_Key':
             raise Exception("This is not a private key thus cannot be loaded.")
         if self._curves_id.has_key(j['curve']):
             curve = self._curves_id[j['curve']]
         else:
             raise Exception("Unrecognized EC curve specified.")
         pkdata = self._trim_keydata(j['data'],True,False)
     except Exception,e:
         raise Exception("Failed loading privatekey. Bad format.")
     # If parsable, Write down and load.
     try:
         membuff = BIO.MemoryBuffer()
         membuff.write(pkdata)
         self._key = EC.load_key_bio(membuff)  #(filename)
         self._key_curve = curve
     except Exception,e:
         raise Exception("Cannot load private key. Error: %s" % e)
     # Override existing public key.
     self._pubkey_curve = curve
     self._derive_pubkey()
     # succeeded.
     return True
 def get_publickey(self,raw=False):
     if self._pubkey == None or self._pubkey_curve == None:
         return False
     # Retrive pubkey data
     membuff = BIO.MemoryBuffer()
     self._pubkey.save_pub_key_bio(membuff)  #(filename)
     pubkeydata = membuff.read_all()  #open(filename).read()
Exemple #24
0
    def test_u2f_unsupported_openssl_missing_curve(self):
        """
        Try registration with an OpenSSL missing the NIST P-256 curve and check the error messages
        """
        skip_test = True

        # Only allow OpenSSL >=1.0.0 with missing EC support
        version_text = m2.OPENSSL_VERSION_TEXT
        match = re.match(r"OpenSSL (?P<version>\d\.\d\.\d)", version_text)
        if match is None:
            # Fail on unknown OpenSSL version string format
            self.fail(
                "Could not detect OpenSSL version - unknown version string format: '%s'"
                % version_text)
        else:
            if match.group('version')[0] != '0':
                # Only run test on missing NIST P-256 curve support
                try:
                    EC.load_key_bio(
                        BIO.MemoryBuffer(self.ATTESTATION_PRIVATE_KEY_PEM))
                except ValueError:
                    skip_test = False

        if skip_test:
            self.skipTest("This test can only be run with OpenSSL missing the "
                          "NIST P-256 curve!")

        # Initial token registration step
        response_registration1_JSON = self._registration1()
        self.assertTrue('"value": true' in response_registration1_JSON,
                        "Response: %r" % response_registration1_JSON)
        self.assertTrue('"challenge":' in response_registration1_JSON,
                        "Response: %r" % response_registration1_JSON)
        self.assertTrue('"serial":' in response_registration1_JSON,
                        "Response: %r" % response_registration1_JSON)

        response_registration1 = json.loads(response_registration1_JSON.body)
        challenge_registration = response_registration1.get(
            'detail', {}).get('challenge')
        self.serial = response_registration1.get('detail', {}).get('serial')
        self.serials.add(self.serial)

        client_data_registration = self._createClientDataObject(
            'registration',
            challenge_registration,
        )
        # Since we have no supported OpenSSL version to calculate the registration response
        # we use a hard-coded correctly-formed fake registration response
        registration_response = binascii.unhexlify(
            self.FAKE_REGISTRATION_DATA_HEX)
        registration_response_message = {
            'registrationData':
            base64.urlsafe_b64encode(registration_response),
            'clientData': base64.urlsafe_b64encode(client_data_registration)
        }

        # Complete the token registration
        response_registration2_JSON = \
            self._registration2(json.dumps(registration_response_message))

        # Registration must fail
        self.assertTrue('"status": false' in response_registration2_JSON,
                        "Response: %r" % response_registration2_JSON)

        # Check for correct error messages
        self.assertTrue(
            'missing ECDSA support for the NIST P-256 curve in OpenSSL'
            in response_registration2_JSON,
            "Response: %r" % response_registration2_JSON)
Exemple #25
0
def load(request):
    """ method dedicated to certificate importation
    :param request: Django POST request object
    :param POST['cert']: The PEM X509 certificate
    :param POST['key']: The PEM X509 key
    :param POST['chain']: The PEM X509 certificate chain
    """
    cert = SSLCertificate()
    cert.cert = ""
    cert.key = ""
    cert.chain = ""
    if request.method == 'POST':
        dataPosted = request.POST

        error = dict()
        err = None
        try:
            cert_cert = dataPosted['cert']
        except:
            err = True
            error['cert'] = "X509 PEM Certificate required"
            pass

        try:
            cert_key = dataPosted['key']
        except:
            err = True
            error['key'] = "X509 PEM Key required"
            pass

        try:
            cert.chain = str(dataPosted['chain'])
        except:
            pass

        if err:
            return render_to_response('cert_import.html', {
                'cert': cert,
                'error': error
            },
                                      context_instance=RequestContext(request))

        # Check the certificate
        try:
            x509Cert = X509.load_cert_string(bytes(cert_cert, 'utf8'))
            cert.cert = str(cert_cert)
        except:
            error['cert'] = "Invalid X509 PEM Certificate"
            return render_to_response('cert_import.html', {
                'cert': cert,
                'error': error
            },
                                      context_instance=RequestContext(request))

        global keypass
        try:
            keypass = str(dataPosted['keypass'])
        except:
            pass

        # Check the private key
        try:
            bio = BIO.MemoryBuffer(bytes(cert_key, 'utf8'))
            RSA.load_key_bio(bio, callback=read_pass_from_POST)
            cert.key = str(cert_key)
        except RSA.RSAError:
            try:
                bio = BIO.MemoryBuffer(bytes(cert_key, 'utf8'))
                EC.load_key_bio(bio, callback=read_pass_from_POST)
                cert.key = str(cert_key)
            except RSA.RSAError:
                error['keypass'] = "******"
            except Exception as e:
                logger.exception(e)
                error['key'] = "Invalid PEM KEY"
        except Exception as e:
            logger.exception(e)
            error['key'] = "Invalid PEM KEY"

        if error:
            return render_to_response('cert_import.html', {
                'cert': cert,
                'error': error
            },
                                      context_instance=RequestContext(request))

        # Store certificate details
        cert.name = str(x509Cert.get_subject())
        cert.status = 'V'
        cert.issuer = str(x509Cert.get_issuer())
        try:
            cert.validfrom = str(x509Cert.get_not_before().get_datetime())
        except Exception as e:
            logger.error(
                "Exception while retrieving validation date 'before' of certificates : "
            )
            logger.exception(e)

        try:
            cert.validtill = str(x509Cert.get_not_after().get_datetime())
        except Exception as e:
            logger.error(
                "Exception while retrieving validation date 'after' of certificates : "
            )
            logger.exception(e)

        if x509Cert.check_ca():
            cert.is_ca = True
        else:
            cert.is_ca = False

        # Find certificate fields
        fields = cert.name.split('/')
        for field in fields:
            tmp = field.split('=')
            if str(tmp[0]) == "CN":
                cert.cn = tmp[1]
            elif str(tmp[0]) == "C":
                cert.c = tmp[1]
            elif str(tmp[0]) == "ST":
                cert.st = tmp[1]
            elif str(tmp[0]) == "L":
                cert.l = tmp[1]
            elif str(tmp[0]) == "O":
                cert.o = tmp[1]
            elif str(tmp[0]) == "OU":
                cert.ou = tmp[1]

        # if cert.cn is empty check if subjectAltName is set en use it
        if (not cert.cn):
            alt_name = x509Cert.get_ext('subjectAltName').get_value()
            if (alt_name):
                cert.cn = alt_name

        cert.save()

        return HttpResponseRedirect('/system/cert/')

    return render_to_response('cert_import.html', {
        'cert': cert,
    },
                              context_instance=RequestContext(request))
Exemple #26
0
 def from_PEM(self, pemkey):
     """import a EC key from a PEM encoded string"""
     m = BIO.MemoryBuffer(pemkey)
     self._key = EC.load_key_bio(m)
Exemple #27
0
def read_keypair(keypairfilename):
    membuf = BIO.MemoryBuffer(open(keypairfilename, 'rb').read())
    key = EC.load_key_bio(membuf)
    membuf.close()
    return key
Exemple #28
0
ephpub, ciphertext = cryptimage.parse_input(data)
ephemeral = EC.pub_key_from_der(cryptimage.build_asn1(ephpub))

if debug: sys.stderr.write("ct = %s\n" % binascii.b2a_hex(ciphertext))

ecpairpem = """-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIH8TNBOfV+JWVBr25KfjJ1007paZ/JnrvjxFzZThUgSToAoGCCqGSM49
AwEHoUQDQgAEtv1eCFuapm3ku1AdTt5eK1IVaAzH2MBQqreo3FBSE8EHxCsEGRvK
auFV+AgDEQotZbdqzAojRoCjuhZcYP73Pg==
-----END EC PRIVATE KEY-----
"""

#derive shared key
ecbio = BIO.MemoryBuffer()
ecbio.write(ecpairpem)
ecpair = EC.load_key_bio(ecbio)
ecder = ecpair.pub().get_der()
ecpub = cryptimage.compress_key(cryptimage.strip_asn1(ecder))

digest = EVP.MessageDigest("sha1")
digest.update(ecpub)
fingerprint = digest.digest()

shared = ecpair.compute_dh_key(ephemeral.pub())

dk=cryptimage.KDF(shared[:len(shared)/2],128,fingerprint)

#decrypt message, extract contents and print results
plaintext = cryptimage.decrypt_data(dk,ciphertext)
[account,amount,pin]=cryptimage.datadecode(plaintext)
print "Destination account number is: " + account