diff --git a/keyserver/addons/rust-node-addon/src/identity_client.rs b/keyserver/addons/rust-node-addon/src/identity_client.rs
--- a/keyserver/addons/rust-node-addon/src/identity_client.rs
+++ b/keyserver/addons/rust-node-addon/src/identity_client.rs
@@ -31,10 +31,9 @@
 #[instrument(skip_all)]
 pub async fn register_user(
   user_id: String,
-  device_id: String,
+  signing_public_key: String,
   username: String,
   password: String,
-  user_public_key: String,
 ) -> Result<String> {
   let channel = Channel::from_static(&IDENTITY_SERVICE_SOCKET_ADDR)
     .connect()
@@ -68,10 +67,9 @@
   let (registration_request, client_registration) = pake_registration_start(
     &mut client_rng,
     user_id,
+    signing_public_key,
     &password,
-    device_id,
     username,
-    user_public_key,
   )?;
   send_to_mpsc(tx.clone(), registration_request).await?;
 
@@ -163,10 +161,9 @@
 fn pake_registration_start(
   rng: &mut (impl Rng + CryptoRng),
   user_id: String,
+  signing_public_key: String,
   password: &str,
-  device_id: String,
   username: String,
-  user_public_key: String,
 ) -> Result<(RegistrationRequest, ClientRegistration<Cipher>)> {
   let client_registration_start_result =
     ClientRegistration::<Cipher>::start(rng, password.as_bytes()).map_err(
@@ -182,10 +179,9 @@
       data: Some(PakeRegistrationRequestAndUserId(
         PakeRegistrationRequestAndUserIdStruct {
           user_id,
-          device_id,
           pake_registration_request,
           username,
-          user_public_key,
+          signing_public_key,
         },
       )),
     },
diff --git a/native/native_rust_library/src/identity_client.rs b/native/native_rust_library/src/identity_client.rs
--- a/native/native_rust_library/src/identity_client.rs
+++ b/native/native_rust_library/src/identity_client.rs
@@ -58,7 +58,7 @@
 pub async fn verify_user_token(
   mut client: Box<IdentityClient>,
   user_id: String,
-  device_id: String,
+  signing_public_key: String,
   access_token: String,
 ) -> Result<bool, Status> {
   Ok(
@@ -66,7 +66,7 @@
       .identity_client
       .verify_user_token(VerifyUserTokenRequest {
         user_id,
-        device_id,
+        signing_public_key,
         access_token,
       })
       .await?
@@ -78,10 +78,9 @@
 pub async fn register_user(
   mut client: Box<IdentityClient>,
   user_id: String,
-  device_id: String,
+  signing_public_key: String,
   username: String,
   password: String,
-  user_public_key: String,
 ) -> Result<String, Status> {
   // Create a RegistrationRequest channel and use ReceiverStream to turn the
   // MPSC receiver into a Stream for outbound messages
@@ -103,9 +102,8 @@
     &mut client_rng,
     user_id,
     &password,
-    device_id,
+    signing_public_key,
     username,
-    user_public_key,
   )?;
   if let Err(e) = tx.send(registration_request).await {
     error!("Response was dropped: {}", e);
@@ -140,9 +138,8 @@
 pub async fn login_user_pake(
   mut client: Box<IdentityClient>,
   user_id: String,
-  device_id: String,
+  signing_public_key: String,
   password: String,
-  user_public_key: String,
 ) -> Result<String, Status> {
   // Create a LoginRequest channel and use ReceiverStream to turn the
   // MPSC receiver into a Stream for outbound messages
@@ -166,7 +163,7 @@
       data: Some(PakeCredentialRequestAndUserId(
         PakeCredentialRequestAndUserIdStruct {
           user_id,
-          device_id,
+          signing_public_key,
           pake_credential_request: client_login_start_result
             .message
             .serialize()
@@ -174,7 +171,6 @@
               error!("Could not serialize credential request: {}", e);
               Status::failed_precondition("PAKE failure")
             })?,
-          user_public_key,
         },
       )),
     })),
@@ -204,10 +200,9 @@
 pub async fn login_user_wallet(
   mut client: Box<IdentityClient>,
   user_id: String,
-  device_id: String,
+  signing_public_key: String,
   siwe_message: String,
   siwe_signature: Vec<u8>,
-  user_public_key: String,
 ) -> Result<String, Status> {
   // Create a LoginRequest channel and use ReceiverStream to turn the
   // MPSC receiver into a Stream for outbound messages
@@ -227,10 +222,9 @@
   let login_request = LoginRequest {
     data: Some(WalletLoginRequest(WalletLoginRequestStruct {
       user_id,
-      device_id,
+      signing_public_key,
       siwe_message,
       siwe_signature,
-      user_public_key,
     })),
   };
   if let Err(e) = tx.send(login_request).await {
@@ -247,9 +241,8 @@
   rng: &mut (impl Rng + CryptoRng),
   user_id: String,
   password: &str,
-  device_id: String,
+  signing_public_key: String,
   username: String,
-  user_public_key: String,
 ) -> Result<(RegistrationRequest, ClientRegistration<Cipher>), Status> {
   let client_registration_start_result =
     ClientRegistration::<Cipher>::start(rng, password.as_bytes()).map_err(
@@ -265,10 +258,9 @@
       data: Some(PakeRegistrationRequestAndUserId(
         PakeRegistrationRequestAndUserIdStruct {
           user_id,
-          device_id,
+          signing_public_key,
           pake_registration_request,
           username,
-          user_public_key,
         },
       )),
     },
diff --git a/native/native_rust_library/src/lib.rs b/native/native_rust_library/src/lib.rs
--- a/native/native_rust_library/src/lib.rs
+++ b/native/native_rust_library/src/lib.rs
@@ -55,7 +55,7 @@
     fn identity_verify_user_token_blocking(
       client: Box<IdentityClient>,
       user_id: String,
-      device_id: String,
+      signing_public_key: String,
       access_token: String,
     ) -> Result<bool>;
 
@@ -63,29 +63,26 @@
     fn identity_register_user_blocking(
       client: Box<IdentityClient>,
       user_id: String,
-      device_id: String,
+      signing_public_key: String,
       username: String,
       password: String,
-      user_public_key: String,
     ) -> Result<String>;
 
     #[cxx_name = "identityLoginUserPakeBlocking"]
     fn identity_login_user_pake_blocking(
       client: Box<IdentityClient>,
       user_id: String,
-      device_id: String,
+      signing_public_key: String,
       password: String,
-      user_public_key: String,
     ) -> Result<String>;
 
     #[cxx_name = "identityLoginUserWalletBlocking"]
     fn identity_login_user_wallet_blocking(
       client: Box<IdentityClient>,
       user_id: String,
-      device_id: String,
+      signing_public_key: String,
       siwe_message: String,
       siwe_signature: Vec<u8>,
-      user_public_key: String,
     ) -> Result<String>;
 
     // Tunnelbroker Service Client
@@ -125,13 +122,13 @@
 fn identity_verify_user_token_blocking(
   client: Box<IdentityClient>,
   user_id: String,
-  device_id: String,
+  signing_public_key: String,
   access_token: String,
 ) -> Result<bool, Status> {
   RUNTIME.block_on(identity_client::verify_user_token(
     client,
     user_id,
-    device_id,
+    signing_public_key,
     access_token,
   ))
 }
@@ -140,18 +137,16 @@
 fn identity_register_user_blocking(
   client: Box<IdentityClient>,
   user_id: String,
-  device_id: String,
+  signing_public_key: String,
   username: String,
   password: String,
-  user_public_key: String,
 ) -> Result<String, Status> {
   RUNTIME.block_on(identity_client::register_user(
     client,
     user_id,
-    device_id,
+    signing_public_key,
     username,
     password,
-    user_public_key,
   ))
 }
 
@@ -159,16 +154,14 @@
 fn identity_login_user_pake_blocking(
   client: Box<IdentityClient>,
   user_id: String,
-  device_id: String,
+  signing_public_key: String,
   password: String,
-  user_public_key: String,
 ) -> Result<String, Status> {
   RUNTIME.block_on(identity_client::login_user_pake(
     client,
     user_id,
-    device_id,
+    signing_public_key,
     password,
-    user_public_key,
   ))
 }
 
@@ -176,18 +169,16 @@
 fn identity_login_user_wallet_blocking(
   client: Box<IdentityClient>,
   user_id: String,
-  device_id: String,
+  signing_public_key: String,
   siwe_message: String,
   siwe_signature: Vec<u8>,
-  user_public_key: String,
 ) -> Result<String, Status> {
   RUNTIME.block_on(identity_client::login_user_wallet(
     client,
     user_id,
-    device_id,
+    signing_public_key,
     siwe_message,
     siwe_signature,
-    user_public_key,
   ))
 }
 
diff --git a/services/identity/src/constants.rs b/services/identity/src/constants.rs
--- a/services/identity/src/constants.rs
+++ b/services/identity/src/constants.rs
@@ -10,16 +10,15 @@
 pub const USERS_TABLE_PARTITION_KEY: &str = "userID";
 pub const USERS_TABLE_REGISTRATION_ATTRIBUTE: &str = "pakeRegistrationData";
 pub const USERS_TABLE_USERNAME_ATTRIBUTE: &str = "username";
-pub const USERS_TABLE_USER_PUBLIC_KEY_ATTRIBUTE: &str = "userPublicKey";
 pub const USERS_TABLE_DEVICES_ATTRIBUTE: &str = "devices";
-pub const USERS_TABLE_DEVICES_MAP_ATTRIBUTE_NAME: &str = "deviceID";
+pub const USERS_TABLE_DEVICES_MAP_ATTRIBUTE_NAME: &str = "signingPublicKey";
 pub const USERS_TABLE_WALLET_ADDRESS_ATTRIBUTE: &str = "walletAddress";
 pub const USERS_TABLE_USERNAME_INDEX: &str = "username-index";
 pub const USERS_TABLE_WALLET_ADDRESS_INDEX: &str = "walletAddress-index";
 
 pub const ACCESS_TOKEN_TABLE: &str = "identity-tokens";
 pub const ACCESS_TOKEN_TABLE_PARTITION_KEY: &str = "userID";
-pub const ACCESS_TOKEN_SORT_KEY: &str = "deviceID";
+pub const ACCESS_TOKEN_SORT_KEY: &str = "signingPublicKey";
 pub const ACCESS_TOKEN_TABLE_CREATED_ATTRIBUTE: &str = "created";
 pub const ACCESS_TOKEN_TABLE_AUTH_TYPE_ATTRIBUTE: &str = "authType";
 pub const ACCESS_TOKEN_TABLE_VALID_ATTRIBUTE: &str = "valid";
diff --git a/services/identity/src/database.rs b/services/identity/src/database.rs
--- a/services/identity/src/database.rs
+++ b/services/identity/src/database.rs
@@ -22,8 +22,7 @@
   USERS_TABLE_DEVICES_ATTRIBUTE, USERS_TABLE_DEVICES_MAP_ATTRIBUTE_NAME,
   USERS_TABLE_PARTITION_KEY, USERS_TABLE_REGISTRATION_ATTRIBUTE,
   USERS_TABLE_USERNAME_ATTRIBUTE, USERS_TABLE_USERNAME_INDEX,
-  USERS_TABLE_USER_PUBLIC_KEY_ATTRIBUTE, USERS_TABLE_WALLET_ADDRESS_ATTRIBUTE,
-  USERS_TABLE_WALLET_ADDRESS_INDEX,
+  USERS_TABLE_WALLET_ADDRESS_ATTRIBUTE, USERS_TABLE_WALLET_ADDRESS_INDEX,
 };
 use crate::nonce::NonceData;
 use crate::token::{AccessTokenData, AuthType};
@@ -74,10 +73,9 @@
   pub async fn update_users_table(
     &self,
     user_id: String,
-    device_id: String,
+    signing_public_key: Option<String>,
     registration: Option<ServerRegistration<Cipher>>,
     username: Option<String>,
-    user_public_key: Option<String>,
   ) -> Result<UpdateItemOutput, Error> {
     let mut update_expression_parts = Vec::new();
     let mut expression_attribute_names = HashMap::new();
@@ -96,22 +94,17 @@
       expression_attribute_values
         .insert(":u".to_string(), AttributeValue::S(username));
     };
-    if let Some(public_key) = user_public_key {
+    if let Some(public_key) = signing_public_key {
       update_expression_parts.push(format!(
         "{}.#{} = :k",
         USERS_TABLE_DEVICES_ATTRIBUTE, USERS_TABLE_DEVICES_MAP_ATTRIBUTE_NAME,
       ));
       expression_attribute_names.insert(
         format!("#{}", USERS_TABLE_DEVICES_MAP_ATTRIBUTE_NAME),
-        device_id,
-      );
-      expression_attribute_values.insert(
-        ":k".to_string(),
-        AttributeValue::M(HashMap::from([(
-          USERS_TABLE_USER_PUBLIC_KEY_ATTRIBUTE.to_string(),
-          AttributeValue::S(public_key),
-        )])),
+        public_key,
       );
+      expression_attribute_values
+        .insert(":k".to_string(), AttributeValue::M(HashMap::new()));
     };
 
     self
@@ -142,10 +135,9 @@
   pub async fn add_user_to_users_table(
     &self,
     user_id: String,
-    device_id: String,
     registration: ServerRegistration<Cipher>,
     username: String,
-    user_public_key: String,
+    signing_public_key: String,
   ) -> Result<PutItemOutput, Error> {
     let item = HashMap::from([
       (
@@ -163,11 +155,8 @@
       (
         USERS_TABLE_DEVICES_ATTRIBUTE.to_string(),
         AttributeValue::M(HashMap::from([(
-          device_id,
-          AttributeValue::M(HashMap::from([(
-            USERS_TABLE_USER_PUBLIC_KEY_ATTRIBUTE.to_string(),
-            AttributeValue::S(user_public_key),
-          )])),
+          signing_public_key,
+          AttributeValue::M(HashMap::new()),
         )])),
       ),
     ]);
@@ -213,14 +202,17 @@
   pub async fn get_access_token_data(
     &self,
     user_id: String,
-    device_id: String,
+    signing_public_key: String,
   ) -> Result<Option<AccessTokenData>, Error> {
     let primary_key = create_composite_primary_key(
       (
         ACCESS_TOKEN_TABLE_PARTITION_KEY.to_string(),
         user_id.clone(),
       ),
-      (ACCESS_TOKEN_SORT_KEY.to_string(), device_id.clone()),
+      (
+        ACCESS_TOKEN_SORT_KEY.to_string(),
+        signing_public_key.clone(),
+      ),
     );
     let get_item_result = self
       .client
@@ -249,7 +241,7 @@
         )?;
         Ok(Some(AccessTokenData {
           user_id,
-          device_id,
+          signing_public_key,
           access_token,
           created,
           auth_type,
@@ -258,15 +250,15 @@
       }
       Ok(_) => {
         info!(
-          "No item found for user {} and device {} in token table",
-          user_id, device_id
+          "No item found for user {} and signing public key {} in token table",
+          user_id, signing_public_key
         );
         Ok(None)
       }
       Err(e) => {
         error!(
-          "DynamoDB client failed to get token for user {} on device {}: {}",
-          user_id, device_id, e
+          "DynamoDB client failed to get token for user {} with signing public key {}: {}",
+          user_id, signing_public_key, e
         );
         Err(Error::AwsSdk(e.into()))
       }
@@ -284,7 +276,7 @@
       ),
       (
         ACCESS_TOKEN_SORT_KEY.to_string(),
-        AttributeValue::S(access_token_data.device_id),
+        AttributeValue::S(access_token_data.signing_public_key),
       ),
       (
         ACCESS_TOKEN_TABLE_TOKEN_ATTRIBUTE.to_string(),
diff --git a/services/identity/src/service.rs b/services/identity/src/service.rs
--- a/services/identity/src/service.rs
+++ b/services/identity/src/service.rs
@@ -172,7 +172,7 @@
     let message = request.into_inner();
     let token_valid = match self
       .client
-      .get_access_token_data(message.user_id, message.device_id)
+      .get_access_token_data(message.user_id, message.signing_public_key)
       .await
     {
       Ok(Some(access_token_data)) => constant_time_eq(
@@ -275,19 +275,19 @@
   client: DatabaseClient,
   auth_type: AuthType,
   user_id: &str,
-  device_id: &str,
+  signing_public_key: &str,
   rng: &mut (impl Rng + CryptoRng),
 ) -> Result<String, Status> {
-  if user_id.is_empty() || device_id.is_empty() {
+  if user_id.is_empty() || signing_public_key.is_empty() {
     error!(
-      "Incomplete data: user ID \"{}\", device ID \"{}\"",
-      user_id, device_id
+      "Incomplete data: user ID \"{}\", signing public key \"{}\"",
+      user_id, signing_public_key
     );
     return Err(Status::aborted("user not found"));
   }
   let access_token_data = AccessTokenData::new(
     user_id.to_string(),
-    device_id.to_string(),
+    signing_public_key.to_string(),
     auth_type,
     rng,
   );
@@ -302,14 +302,14 @@
 
 fn parse_and_verify_siwe_message(
   user_id: &str,
-  device_id: &str,
+  signing_public_key: &str,
   siwe_message: &str,
   siwe_signature: Vec<u8>,
 ) -> Result<(), Status> {
-  if user_id.is_empty() || device_id.is_empty() {
+  if user_id.is_empty() || signing_public_key.is_empty() {
     error!(
-      "Incomplete data: user ID {}, device ID {}",
-      user_id, device_id
+      "Incomplete data: user ID {}, signing public key {}",
+      user_id, signing_public_key
     );
     return Err(Status::aborted("user not found"));
   }
@@ -334,8 +334,8 @@
   ) {
     Err(e) => {
       error!(
-        "Signature verification failed for user {} on device {}: {}",
-        user_id, device_id, e
+        "Signature verification failed for user {} with signing public key {}: {}",
+        user_id, signing_public_key, e
       );
       Err(Status::unauthenticated("message not authenticated"))
     }
@@ -350,17 +350,16 @@
 ) -> Result<LoginResponse, Status> {
   parse_and_verify_siwe_message(
     &wallet_login_request.user_id,
-    &wallet_login_request.device_id,
+    &wallet_login_request.signing_public_key,
     &wallet_login_request.siwe_message,
     wallet_login_request.siwe_signature,
   )?;
   client
     .update_users_table(
       wallet_login_request.user_id.clone(),
-      wallet_login_request.device_id.clone(),
+      Some(wallet_login_request.signing_public_key.clone()),
       None,
       None,
-      Some(wallet_login_request.user_public_key),
     )
     .await
     .map_err(handle_db_error)?;
@@ -370,7 +369,7 @@
         client,
         AuthType::Wallet,
         &wallet_login_request.user_id,
-        &wallet_login_request.device_id,
+        &wallet_login_request.signing_public_key,
         rng,
       )
       .await?,
@@ -430,18 +429,17 @@
 
 async fn pake_login_finish(
   user_id: &str,
-  device_id: &str,
-  user_public_key: &str,
+  signing_public_key: &str,
   client: DatabaseClient,
   server_login: ServerLogin<Cipher>,
   pake_credential_finalization: &[u8],
   rng: &mut (impl Rng + CryptoRng),
   pake_workflow: PakeWorkflow,
 ) -> Result<PakeLoginResponseStruct, Status> {
-  if user_id.is_empty() || device_id.is_empty() {
+  if user_id.is_empty() || signing_public_key.is_empty() {
     error!(
-      "Incomplete data: user ID {}, device ID {}",
-      user_id, device_id
+      "Incomplete data: user ID {}, signing public key {}",
+      user_id, signing_public_key
     );
     return Err(Status::aborted("user not found"));
   }
@@ -464,18 +462,23 @@
     client
       .update_users_table(
         user_id.to_string(),
-        device_id.to_string(),
+        Some(signing_public_key.to_string()),
         None,
         None,
-        Some(user_public_key.to_string()),
       )
       .await
       .map_err(handle_db_error)?;
   }
   Ok(PakeLoginResponseStruct {
     data: Some(AccessToken(
-      put_token_helper(client, AuthType::Password, user_id, device_id, rng)
-        .await?,
+      put_token_helper(
+        client,
+        AuthType::Password,
+        user_id,
+        signing_public_key,
+        rng,
+      )
+      .await?,
     )),
   })
 }
@@ -511,12 +514,11 @@
 
 async fn pake_registration_finish(
   user_id: &str,
-  device_id: &str,
   client: DatabaseClient,
   registration_upload_bytes: &[u8],
   server_registration: Option<ServerRegistration<Cipher>>,
   username: &str,
-  user_public_key: &str,
+  signing_public_key: &str,
 ) -> Result<(), Status> {
   if user_id.is_empty() {
     error!("Incomplete data: user ID not provided");
@@ -543,10 +545,9 @@
   match client
     .add_user_to_users_table(
       user_id.to_string(),
-      device_id.to_string(),
       server_registration_finish_result,
       username.to_string(),
-      user_public_key.to_string(),
+      signing_public_key.to_string(),
     )
     .await
   {
diff --git a/services/identity/src/service/login.rs b/services/identity/src/service/login.rs
--- a/services/identity/src/service/login.rs
+++ b/services/identity/src/service/login.rs
@@ -1,8 +1,7 @@
 use super::*;
 pub struct LoginState {
   user_id: String,
-  device_id: String,
-  user_public_key: String,
+  signing_public_key: String,
   pake_state: ServerLogin<Cipher>,
 }
 pub async fn handle_login_request(
@@ -48,8 +47,8 @@
 
       Ok(Some(LoginState {
         user_id: pake_credential_request_and_user_id.user_id,
-        device_id: pake_credential_request_and_user_id.device_id,
-        user_public_key: pake_credential_request_and_user_id.user_public_key,
+        signing_public_key: pake_credential_request_and_user_id
+          .signing_public_key,
         pake_state: response_and_state.pake_state,
       }))
     }
@@ -72,8 +71,7 @@
     })) => {
       let login_finish_result = pake_login_finish(
         &login_state.user_id,
-        &login_state.device_id,
-        &login_state.user_public_key,
+        &login_state.signing_public_key,
         client,
         login_state.pake_state,
         &pake_credential_finalization,
diff --git a/services/identity/src/service/registration.rs b/services/identity/src/service/registration.rs
--- a/services/identity/src/service/registration.rs
+++ b/services/identity/src/service/registration.rs
@@ -1,9 +1,8 @@
 use super::*;
 pub struct RegistrationState {
   user_id: String,
-  device_id: String,
   username: String,
-  user_public_key: String,
+  signing_public_key: String,
   pub pake_state: Option<ServerRegistration<Cipher>>,
 }
 
@@ -48,9 +47,9 @@
 
       Ok(RegistrationState {
         user_id: pake_registration_request_and_user_id.user_id,
-        device_id: pake_registration_request_and_user_id.device_id,
         username: pake_registration_request_and_user_id.username,
-        user_public_key: pake_registration_request_and_user_id.user_public_key,
+        signing_public_key: pake_registration_request_and_user_id
+          .signing_public_key,
         pake_state: Some(response_and_state.pake_state),
       })
     }
@@ -74,13 +73,12 @@
     })) => {
       let response_and_state = match pake_registration_finish(
         &registration_state.user_id,
-        &registration_state.device_id,
         client.clone(),
         &pake_registration_upload_and_credential_request
           .pake_registration_upload,
         Some(pake_state),
         &registration_state.username,
-        &registration_state.user_public_key,
+        &registration_state.signing_public_key,
       )
       .await
       {
@@ -126,8 +124,7 @@
     })) => {
       let login_finish_result = pake_login_finish(
         &registration_state.user_id,
-        &registration_state.device_id,
-        &registration_state.user_public_key,
+        &registration_state.signing_public_key,
         client,
         server_login,
         &pake_credential_finalization,
diff --git a/services/identity/src/token.rs b/services/identity/src/token.rs
--- a/services/identity/src/token.rs
+++ b/services/identity/src/token.rs
@@ -15,7 +15,7 @@
 #[derive(Clone)]
 pub struct AccessTokenData {
   pub user_id: String,
-  pub device_id: String,
+  pub signing_public_key: String,
   pub access_token: String,
   pub created: DateTime<Utc>,
   pub auth_type: AuthType,
@@ -25,13 +25,13 @@
 impl AccessTokenData {
   pub fn new(
     user_id: String,
-    device_id: String,
+    signing_public_key: String,
     auth_type: AuthType,
     rng: &mut (impl Rng + CryptoRng),
   ) -> Self {
     AccessTokenData {
       user_id,
-      device_id,
+      signing_public_key,
       access_token: Alphanumeric.sample_string(rng, ACCESS_TOKEN_LENGTH),
       created: Utc::now(),
       auth_type,
diff --git a/services/terraform/dynamodb.tf b/services/terraform/dynamodb.tf
--- a/services/terraform/dynamodb.tf
+++ b/services/terraform/dynamodb.tf
@@ -196,7 +196,7 @@
 resource "aws_dynamodb_table" "identity-tokens" {
   name           = "identity-tokens"
   hash_key       = "userID"
-  range_key      = "deviceID"
+  range_key      = "signingPublicKey"
   write_capacity = 10
   read_capacity  = 10
 
@@ -206,7 +206,7 @@
   }
 
   attribute {
-    name = "deviceID"
+    name = "signingPublicKey"
     type = "S"
   }
 }
diff --git a/shared/protos/identity.proto b/shared/protos/identity.proto
--- a/shared/protos/identity.proto
+++ b/shared/protos/identity.proto
@@ -28,19 +28,19 @@
 
 message PakeRegistrationRequestAndUserID {
   string userID = 1;
-  string deviceID = 2;
+  // ed25519 key for the given user's device
+  string signingPublicKey = 2;
   // Message sent to initiate PAKE registration (step 1)
   bytes pakeRegistrationRequest = 3;
   string username = 4;
-  string userPublicKey = 5;
 }
 
 message PakeCredentialRequestAndUserID {
   string userID = 1;
-  string deviceID = 2;
+  // ed25519 key for the given user's device
+  string signingPublicKey = 2;
   // Message sent to initiate PAKE login (step 1)
   bytes pakeCredentialRequest = 3;
-  string userPublicKey = 4;
 }
 
 message PakeLoginRequest {
@@ -71,10 +71,10 @@
 
 message WalletLoginRequest {
   string userID = 1;
-  string deviceID = 2;
+  // ed25519 key for the given user's device
+  string signingPublicKey = 2;
   string siweMessage = 3;
   bytes siweSignature = 4;
-  string userPublicKey = 5;
 }
 
 message WalletLoginResponse {
@@ -124,7 +124,8 @@
 
 message VerifyUserTokenRequest {
   string userID = 1;
-  string deviceID = 2;
+  // ed25519 key for the given user's device
+  string signingPublicKey = 2;
   string accessToken = 3;
 }