diff --git a/keyserver/src/responders/landing-handler.js b/keyserver/src/responders/landing-handler.js
--- a/keyserver/src/responders/landing-handler.js
+++ b/keyserver/src/responders/landing-handler.js
@@ -13,6 +13,7 @@
   isValidPrimaryIdentityPublicKey,
   isValidSIWENonce,
   isValidSIWEMessageType,
+  isValidSIWEIssuedAt,
 } from 'lib/utils/siwe-utils.js';
 
 import { getMessageForException } from './utils.js';
@@ -153,6 +154,18 @@
   }
   const siweMessageType = ((siweMessageTypeRawString: any): SIWEMessageType);
 
+  const siweMessageIssuedAt = req.header('siwe-message-issued-at');
+  if (
+    siweMessageIssuedAt !== null &&
+    siweMessageIssuedAt !== undefined &&
+    !isValidSIWEIssuedAt(siweMessageIssuedAt)
+  ) {
+    res.status(400).send({
+      message: 'Invalid siwe message issued at.',
+    });
+    return;
+  }
+
   const [{ jsURL, fontURLs, cssInclude }, LandingSSR] = await Promise.all([
     getAssetInfo(),
     getWebpackCompiledRootComponentForSSR(),
@@ -215,6 +228,7 @@
       siweNonce={siweNonce}
       siwePrimaryIdentityPublicKey={siwePrimaryIdentityPublicKey}
       siweMessageType={siweMessageType}
+      siweMessageIssuedAt={siweMessageIssuedAt}
     />,
   );
   reactStream.pipe(res, { end: false });
@@ -227,12 +241,16 @@
   const siweMessageTypeString = siweMessageType
     ? `"${siweMessageType}"`
     : 'null';
+  const siweMessageIssuedAtString = siweMessageIssuedAt
+    ? `"${siweMessageIssuedAt}"`
+    : 'null';
   // prettier-ignore
   res.end(html`</div>
         <script>var routerBasename = "${routerBasename}";</script>
         <script>var siweNonce = ${siweNonceString};</script>
         <script>var siwePrimaryIdentityPublicKey = ${siwePrimaryIdentityPublicKeyString};</script>
         <script>var siweMessageType = ${siweMessageTypeString};</script>
+        <script>var siweMessageIssuedAt = ${siweMessageIssuedAtString};</script>
         <script src="${jsURL}"></script>
       </body>
     </html>
diff --git a/landing/landing-ssr.react.js b/landing/landing-ssr.react.js
--- a/landing/landing-ssr.react.js
+++ b/landing/landing-ssr.react.js
@@ -14,6 +14,7 @@
   +siweNonce: ?string,
   +siwePrimaryIdentityPublicKey: ?string,
   +siweMessageType: ?SIWEMessageType,
+  +siweMessageIssuedAt: ?string,
 };
 function LandingSSR(props: LandingSSRProps): React.Node {
   const {
@@ -22,6 +23,7 @@
     siweNonce,
     siwePrimaryIdentityPublicKey,
     siweMessageType,
+    siweMessageIssuedAt,
   } = props;
 
   const siweContextValue = React.useMemo(
@@ -29,8 +31,14 @@
       siweNonce,
       siwePrimaryIdentityPublicKey,
       siweMessageType,
+      siweMessageIssuedAt,
     }),
-    [siweNonce, siwePrimaryIdentityPublicKey, siweMessageType],
+    [
+      siweNonce,
+      siwePrimaryIdentityPublicKey,
+      siweMessageType,
+      siweMessageIssuedAt,
+    ],
   );
   const routerContext = React.useMemo(() => ({}), []);
   return (
diff --git a/landing/root.js b/landing/root.js
--- a/landing/root.js
+++ b/landing/root.js
@@ -12,6 +12,7 @@
 declare var siweNonce: ?string;
 declare var siwePrimaryIdentityPublicKey: ?string;
 declare var siweMessageType: ?SIWEMessageType;
+declare var siweMessageIssuedAt: ?string;
 
 function RootComponent(): React.Node {
   const siweContextValue = React.useMemo(
@@ -19,6 +20,7 @@
       siweNonce,
       siwePrimaryIdentityPublicKey,
       siweMessageType,
+      siweMessageIssuedAt,
     }),
     [],
   );
diff --git a/landing/siwe-context.js b/landing/siwe-context.js
--- a/landing/siwe-context.js
+++ b/landing/siwe-context.js
@@ -8,12 +8,14 @@
   +siweNonce: ?string,
   +siwePrimaryIdentityPublicKey: ?string,
   +siweMessageType: ?SIWEMessageType,
+  +siweMessageIssuedAt: ?string,
 };
 
 const SIWEContext: React.Context<SIWEContextType> = React.createContext({
   siweNonce: null,
   siwePrimaryIdentityPublicKey: null,
   siweMessageType: null,
+  siweMessageIssuedAt: null,
 });
 
 export { SIWEContext };
diff --git a/landing/siwe.react.js b/landing/siwe.react.js
--- a/landing/siwe.react.js
+++ b/landing/siwe.react.js
@@ -13,7 +13,10 @@
 import { useAccount, useWalletClient, WagmiProvider } from 'wagmi';
 
 import ConnectedWalletInfo from 'lib/components/connected-wallet-info.react.js';
-import { type SIWEWebViewMessage } from 'lib/types/siwe-types.js';
+import {
+  type SIWEWebViewMessage,
+  SIWEMessageTypes,
+} from 'lib/types/siwe-types.js';
 import {
   getSIWEStatementForPublicKey,
   userTextsForSIWEMessageTypes,
@@ -51,9 +54,10 @@
   signer: Signer,
   nonce: string,
   statement: string,
+  issuedAt: ?string,
 ) {
   invariant(nonce, 'nonce must be present in signInWithEthereum');
-  const message = createSIWEMessage(address, statement, nonce);
+  const message = createSIWEMessage(address, statement, nonce, issuedAt);
   const signature = await signer.signMessage({ message });
   postMessageToNativeWebView({
     type: 'siwe_success',
@@ -68,8 +72,13 @@
 function SIWE(): React.Node {
   const { address } = useAccount();
   const { data: signer } = useWalletClient();
-  const { siweNonce, siwePrimaryIdentityPublicKey, siweMessageType } =
-    React.useContext(SIWEContext);
+  const {
+    siweNonce,
+    siwePrimaryIdentityPublicKey,
+    siweMessageType,
+    siweMessageIssuedAt,
+  } = React.useContext(SIWEContext);
+
   const onClick = React.useCallback(() => {
     invariant(siweNonce, 'nonce must be present during SIWE attempt');
     invariant(siweMessageType, 'message type must be set during SIWE attempt');
@@ -81,13 +90,20 @@
       siwePrimaryIdentityPublicKey,
       siweMessageType,
     );
-    void signInWithEthereum(address, signer, siweNonce, statement);
+    void signInWithEthereum(
+      address,
+      signer,
+      siweNonce,
+      statement,
+      siweMessageIssuedAt,
+    );
   }, [
     address,
     signer,
     siweNonce,
     siwePrimaryIdentityPublicKey,
     siweMessageType,
+    siweMessageIssuedAt,
   ]);
 
   const { openConnectModal, connectModalOpen } = useConnectModal();
@@ -141,6 +157,18 @@
         <h1 className={css.h1}>Unable to proceed: nonce not found.</h1>
       </div>
     );
+  }
+  if (
+    siweMessageType === SIWEMessageTypes.MSG_BACKUP_RESTORE &&
+    !siweMessageIssuedAt
+  ) {
+    return (
+      <div className={css.wrapper}>
+        <h1 className={css.h1}>
+          Unable to proceed: issuedAt type not found for msg_backup_restore
+        </h1>
+      </div>
+    );
   } else if (!signer) {
     return null;
   } else {
diff --git a/lib/types/siwe-types.js b/lib/types/siwe-types.js
--- a/lib/types/siwe-types.js
+++ b/lib/types/siwe-types.js
@@ -141,10 +141,20 @@
 export const SIWEMessageTypes = Object.freeze({
   MSG_AUTH: 'msg_auth',
   MSG_BACKUP: 'msg_backup',
+  MSG_BACKUP_RESTORE: 'msg_backup_restore',
 });
 
 export type SIWEMessageType = $Values<typeof SIWEMessageTypes>;
 
+export type SIWESignatureRequestData =
+  | { +messageType: SIWEMessageType }
+  | {
+      +messageType: 'msg_backup_restore',
+      +siweNonce: string,
+      +siweStatement: string,
+      +siweIssuedAt: string,
+    };
+
 export type SIWEBackupSecrets = {
   +message: string,
   +signature: string,
diff --git a/lib/utils/siwe-utils.js b/lib/utils/siwe-utils.js
--- a/lib/utils/siwe-utils.js
+++ b/lib/utils/siwe-utils.js
@@ -32,6 +32,12 @@
   return siweMessageTypeValidator.is(candidate);
 }
 
+const siweMessageIssuedAtRegex: RegExp =
+  /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)((-(\d{2}):(\d{2})|Z)?)$/;
+function isValidSIWEIssuedAt(candidate: string): boolean {
+  return siweMessageIssuedAtRegex.test(candidate);
+}
+
 const siweStatementLegalAgreement: string =
   'By continuing, I accept the Comm Terms of Service: https://comm.app/terms';
 
@@ -39,6 +45,7 @@
   address: string,
   statement: string,
   nonce: string,
+  issuedAt: ?string,
 ): string {
   invariant(nonce, 'nonce must be present in createSiweMessage');
   const domain = window.location.host;
@@ -47,6 +54,7 @@
     domain,
     address,
     statement,
+    issuedAt,
     uri: origin,
     version: '1',
     chainId: '1',
@@ -134,7 +142,12 @@
   `Your signature on this message will be used to derive ` +
   `a secret key that will encrypt your Comm backup.`;
 
+const siweBackupRestoreMessageSigningExplanationStatements: string =
+  `Your signature on this message will be used to derive ` +
+  `a secret key that will decrypt your Comm backup.`;
+
 const siweBackupMessageSigningButtonStatement = 'Create a backup key';
+const siweBackupRestoreMessageSigningButtonStatement = 'Retrieve a backup key';
 
 const userTextsForSIWEMessageTypes: {
   +[signatureRequestType: string]: {
@@ -153,12 +166,18 @@
     showTermsAgreement: false,
     buttonStatement: siweBackupMessageSigningButtonStatement,
   },
+  [SIWEMessageTypes.MSG_BACKUP_RESTORE]: {
+    explanationStatement: siweBackupRestoreMessageSigningExplanationStatements,
+    showTermsAgreement: false,
+    buttonStatement: siweBackupRestoreMessageSigningButtonStatement,
+  },
 };
 
 export {
   isValidSIWENonce,
   isValidEthereumAddress,
   isValidSIWEMessageType,
+  isValidSIWEIssuedAt,
   primaryIdentityPublicKeyRegex,
   isValidPrimaryIdentityPublicKey,
   createSIWEMessage,