From 1ec746c01411dafa8b2554d8463e2ec5bcd204eb Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 17 Jan 2020 19:53:33 -0700 Subject: [PATCH 1/6] Add verification with QR codes --- src/MatrixClientPeg.js | 2 +- .../elements/crypto/VerificationQRCode.js | 59 +++++++++++++++++++ .../views/right_panel/VerificationPanel.js | 22 ++++++- 3 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 src/components/views/elements/crypto/VerificationQRCode.js diff --git a/src/MatrixClientPeg.js b/src/MatrixClientPeg.js index dbc570c872..450bec8e77 100644 --- a/src/MatrixClientPeg.js +++ b/src/MatrixClientPeg.js @@ -217,7 +217,7 @@ class _MatrixClientPeg { timelineSupport: true, forceTURN: !SettingsStore.getValue('webRtcAllowPeerToPeer', false), fallbackICEServerAllowed: !!SettingsStore.getValue('fallbackICEServerAllowed'), - verificationMethods: [verificationMethods.SAS], + verificationMethods: [verificationMethods.SAS, verificationMethods.QR_CODE_SHOW], unstableClientRelationAggregation: true, identityServer: new IdentityAuthClient(), }; diff --git a/src/components/views/elements/crypto/VerificationQRCode.js b/src/components/views/elements/crypto/VerificationQRCode.js new file mode 100644 index 0000000000..c49dd3faf5 --- /dev/null +++ b/src/components/views/elements/crypto/VerificationQRCode.js @@ -0,0 +1,59 @@ +/* +Copyright 2020 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React from "react"; +import PropTypes from "prop-types"; +import {replaceableComponent} from "../../../../utils/replaceableComponent"; +import * as qs from "qs"; +import QRCode from "qrcode-react"; + +@replaceableComponent("views.elements.crypto.VerificationQRCode") +export default class VerificationQRCode extends React.PureComponent { + static propTypes = { + // Common for all kinds of QR codes + keys: PropTypes.array.isRequired, // array of [Key ID, Key] pairs + action: PropTypes.string.isRequired, + keyholderUserId: PropTypes.string.isRequired, + + // User verification use case only + secret: PropTypes.string, + otherUserKey: PropTypes.string, + verificationKey: PropTypes.string, + verificationAlgorithms: PropTypes.array, + requestEventId: PropTypes.string, + }; + + static defaultProps = { + action: "verify", + }; + + render() { + const query = { + request: this.props.requestEventId, + action: this.props.action, + verification_algorithms: this.props.verificationAlgorithms, + verification_key: this.props.verificationKey, + other_user_key: this.props.otherUserKey, + }; + for (const key of this.props.keys) { + query[`key_${key[0]}`] = key[1]; + } + + const uri = `https://matrix.to/#/${this.props.keyholderUserId}?${qs.stringify(query)}`; + + return + } +} diff --git a/src/components/views/right_panel/VerificationPanel.js b/src/components/views/right_panel/VerificationPanel.js index 0d28e1568f..a2038087fc 100644 --- a/src/components/views/right_panel/VerificationPanel.js +++ b/src/components/views/right_panel/VerificationPanel.js @@ -17,6 +17,9 @@ limitations under the License. import React from 'react'; import * as sdk from '../../../index'; import {verificationMethods} from 'matrix-js-sdk/src/crypto'; +import VerificationQRCode from "../elements/crypto/VerificationQRCode"; +import {VerificationRequest} from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest"; +import {MatrixClientPeg} from "../../../MatrixClientPeg"; export default class VerificationPanel extends React.PureComponent { constructor(props) { @@ -36,15 +39,30 @@ export default class VerificationPanel extends React.PureComponent { renderStatus() { const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); const Spinner = sdk.getComponent('elements.Spinner'); - const {request} = this.props; + const {request: req} = this.props; + const request: VerificationRequest = req; if (request.requested) { return (

Waiting for {request.otherUserId} to accept ...

); } else if (request.ready) { + const qrCodeKeys = [ + [MatrixClientPeg.get().getDeviceId(), MatrixClientPeg.get().getDeviceEd25519Key()], + [MatrixClientPeg.get().getCrossSigningId(), MatrixClientPeg.get().getCrossSigningKey("master")], + ]; + // TODO: Await a bunch of this + const otherCrossSigning = MatrixClientPeg.get().getStoredCrossSigningForUser(request.otherUserId); + const otherUserKey = otherCrossSigning ? otherCrossSigning.getCrossSigningKey("master") : null; + const qrCode = ; const verifyButton = Verify by emoji ; - return (

{request.otherUserId} is ready, start {verifyButton}

); + return (

{request.otherUserId} is ready, start {verifyButton} or have them scan: {qrCode}

); } else if (request.started) { if (this.state.sasWaitingForOtherParty) { return

Waiting for {request.otherUserId} to confirm ...

; From 586a240e41721651ae661abb216de865504672bd Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Mon, 20 Jan 2020 23:10:35 -0700 Subject: [PATCH 2/6] Don't use private keys for QR code --- src/components/views/right_panel/VerificationPanel.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/components/views/right_panel/VerificationPanel.js b/src/components/views/right_panel/VerificationPanel.js index a2038087fc..34f7538b1c 100644 --- a/src/components/views/right_panel/VerificationPanel.js +++ b/src/components/views/right_panel/VerificationPanel.js @@ -45,17 +45,15 @@ export default class VerificationPanel extends React.PureComponent { if (request.requested) { return (

Waiting for {request.otherUserId} to accept ...

); } else if (request.ready) { + const keyId = `ed25519:${MatrixClientPeg.get().getCrossSigningId()}`; const qrCodeKeys = [ [MatrixClientPeg.get().getDeviceId(), MatrixClientPeg.get().getDeviceEd25519Key()], - [MatrixClientPeg.get().getCrossSigningId(), MatrixClientPeg.get().getCrossSigningKey("master")], + [keyId, MatrixClientPeg.get().getCrossSigningId()], ]; - // TODO: Await a bunch of this - const otherCrossSigning = MatrixClientPeg.get().getStoredCrossSigningForUser(request.otherUserId); - const otherUserKey = otherCrossSigning ? otherCrossSigning.getCrossSigningKey("master") : null; const qrCode = ; From b682e7d908a8e6b3c84a0e77977604bd85709bf6 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 23 Jan 2020 20:05:32 -0700 Subject: [PATCH 3/6] Generate a QR code for apps to scan --- .../elements/crypto/VerificationQRCode.js | 8 ++--- .../views/right_panel/VerificationPanel.js | 32 +++++++++++-------- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/components/views/elements/crypto/VerificationQRCode.js b/src/components/views/elements/crypto/VerificationQRCode.js index c49dd3faf5..fa4031da9f 100644 --- a/src/components/views/elements/crypto/VerificationQRCode.js +++ b/src/components/views/elements/crypto/VerificationQRCode.js @@ -24,15 +24,13 @@ import QRCode from "qrcode-react"; export default class VerificationQRCode extends React.PureComponent { static propTypes = { // Common for all kinds of QR codes - keys: PropTypes.array.isRequired, // array of [Key ID, Key] pairs + keys: PropTypes.array.isRequired, // array of [Key ID, Base64 Key] pairs action: PropTypes.string.isRequired, keyholderUserId: PropTypes.string.isRequired, // User verification use case only secret: PropTypes.string, - otherUserKey: PropTypes.string, - verificationKey: PropTypes.string, - verificationAlgorithms: PropTypes.array, + otherUserKey: PropTypes.string, // Base64 key being verified requestEventId: PropTypes.string, }; @@ -44,8 +42,6 @@ export default class VerificationQRCode extends React.PureComponent { const query = { request: this.props.requestEventId, action: this.props.action, - verification_algorithms: this.props.verificationAlgorithms, - verification_key: this.props.verificationKey, other_user_key: this.props.otherUserKey, }; for (const key of this.props.keys) { diff --git a/src/components/views/right_panel/VerificationPanel.js b/src/components/views/right_panel/VerificationPanel.js index 34f7538b1c..d0c3d2df10 100644 --- a/src/components/views/right_panel/VerificationPanel.js +++ b/src/components/views/right_panel/VerificationPanel.js @@ -45,22 +45,28 @@ export default class VerificationPanel extends React.PureComponent { if (request.requested) { return (

Waiting for {request.otherUserId} to accept ...

); } else if (request.ready) { - const keyId = `ed25519:${MatrixClientPeg.get().getCrossSigningId()}`; - const qrCodeKeys = [ - [MatrixClientPeg.get().getDeviceId(), MatrixClientPeg.get().getDeviceEd25519Key()], - [keyId, MatrixClientPeg.get().getCrossSigningId()], - ]; - const qrCode = ; const verifyButton = Verify by emoji ; - return (

{request.otherUserId} is ready, start {verifyButton} or have them scan: {qrCode}

); + + if (request.requestEvent && request.requestEvent.getId()) { + const keyId = `ed25519:${MatrixClientPeg.get().getCrossSigningId()}`; + const qrCodeKeys = [ + [MatrixClientPeg.get().getDeviceId(), MatrixClientPeg.get().getDeviceEd25519Key()], + [keyId, MatrixClientPeg.get().getCrossSigningId()], + ]; + const crossSigningInfo = MatrixClientPeg.get().getStoredCrossSigningForUser(request.otherUserId); + const qrCode = ; + return (

{request.otherUserId} is ready, start {verifyButton} or have them scan: {qrCode}

); + } + + return (

{request.otherUserId} is ready, start {verifyButton}

); } else if (request.started) { if (this.state.sasWaitingForOtherParty) { return

Waiting for {request.otherUserId} to confirm ...

; From 0ce9da5d365d4b2e1490206233c8ecfa6dc01eed Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 23 Jan 2020 20:12:24 -0700 Subject: [PATCH 4/6] Appease the linter --- src/components/views/elements/crypto/VerificationQRCode.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/views/elements/crypto/VerificationQRCode.js b/src/components/views/elements/crypto/VerificationQRCode.js index fa4031da9f..9026e51096 100644 --- a/src/components/views/elements/crypto/VerificationQRCode.js +++ b/src/components/views/elements/crypto/VerificationQRCode.js @@ -50,6 +50,6 @@ export default class VerificationQRCode extends React.PureComponent { const uri = `https://matrix.to/#/${this.props.keyholderUserId}?${qs.stringify(query)}`; - return + return ; } } From b7e680ba5154935f3f8a394ceaeeb0bda307c29b Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Thu, 23 Jan 2020 20:14:27 -0700 Subject: [PATCH 5/6] Fix key ID --- src/components/views/right_panel/VerificationPanel.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/views/right_panel/VerificationPanel.js b/src/components/views/right_panel/VerificationPanel.js index d0c3d2df10..a29546c8f7 100644 --- a/src/components/views/right_panel/VerificationPanel.js +++ b/src/components/views/right_panel/VerificationPanel.js @@ -50,10 +50,9 @@ export default class VerificationPanel extends React.PureComponent { ; if (request.requestEvent && request.requestEvent.getId()) { - const keyId = `ed25519:${MatrixClientPeg.get().getCrossSigningId()}`; const qrCodeKeys = [ [MatrixClientPeg.get().getDeviceId(), MatrixClientPeg.get().getDeviceEd25519Key()], - [keyId, MatrixClientPeg.get().getCrossSigningId()], + [MatrixClientPeg.get().getCrossSigningId(), MatrixClientPeg.get().getCrossSigningId()], ]; const crossSigningInfo = MatrixClientPeg.get().getStoredCrossSigningForUser(request.otherUserId); const qrCode = Date: Thu, 23 Jan 2020 20:19:17 -0700 Subject: [PATCH 6/6] Actually add the secret to the QR code url --- src/components/views/elements/crypto/VerificationQRCode.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/views/elements/crypto/VerificationQRCode.js b/src/components/views/elements/crypto/VerificationQRCode.js index 9026e51096..1cb5647317 100644 --- a/src/components/views/elements/crypto/VerificationQRCode.js +++ b/src/components/views/elements/crypto/VerificationQRCode.js @@ -43,6 +43,7 @@ export default class VerificationQRCode extends React.PureComponent { request: this.props.requestEventId, action: this.props.action, other_user_key: this.props.otherUserKey, + secret: this.props.secret, }; for (const key of this.props.keys) { query[`key_${key[0]}`] = key[1];