Skip to content

Commit 69f4dc0

Browse files
authored
Merge pull request #5 from 398ja/develop
develop
2 parents f9c639d + 3603822 commit 69f4dc0

19 files changed

Lines changed: 102 additions & 28 deletions

File tree

nsecbunker-account/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<parent>
99
<groupId>xyz.tcheeric</groupId>
1010
<artifactId>nsecbunker-java</artifactId>
11-
<version>0.1.0</version>
11+
<version>0.1.1</version>
1212
</parent>
1313

1414
<artifactId>nsecbunker-account</artifactId>

nsecbunker-admin/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<parent>
99
<groupId>xyz.tcheeric</groupId>
1010
<artifactId>nsecbunker-java</artifactId>
11-
<version>0.1.0</version>
11+
<version>0.1.1</version>
1212
</parent>
1313

1414
<artifactId>nsecbunker-admin</artifactId>

nsecbunker-admin/src/main/java/xyz/tcheeric/nsecbunker/admin/key/DefaultKeyManager.java

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,20 +58,22 @@ public DefaultKeyManager(NsecBunkerAdminClient adminClient, ObjectMapper objectM
5858
@Override
5959
public CompletableFuture<BunkerKey> createKey(String name, String nsec, String passphrase) {
6060
validateName(name);
61-
requirePassphrase(passphrase);
6261
if (nsec == null || nsec.isBlank()) {
6362
throw new IllegalArgumentException("nsec must not be null or blank");
6463
}
6564

66-
return sendForKey(METHOD_CREATE_NEW_KEY, List.of(name, passphrase, nsec), name);
65+
// Empty passphrase is allowed - nsecbunkerd will store the key unencrypted
66+
String normalizedPassphrase = normalizePassphrase(passphrase);
67+
return sendForKey(METHOD_CREATE_NEW_KEY, List.of(name, normalizedPassphrase, nsec), name);
6768
}
6869

6970
@Override
7071
public CompletableFuture<BunkerKey> createKey(String name, String passphrase) {
7172
validateName(name);
72-
requirePassphrase(passphrase);
7373

74-
return sendForKey(METHOD_CREATE_NEW_KEY, List.of(name, passphrase), name);
74+
// Empty passphrase is allowed - nsecbunkerd will store the key unencrypted
75+
String normalizedPassphrase = normalizePassphrase(passphrase);
76+
return sendForKey(METHOD_CREATE_NEW_KEY, List.of(name, normalizedPassphrase), name);
7577
}
7678

7779
@Override
@@ -83,9 +85,10 @@ public CompletableFuture<List<BunkerKey>> listKeys() {
8385
@Override
8486
public CompletableFuture<Boolean> unlockKey(String name, String passphrase) {
8587
validateName(name);
86-
requirePassphrase(passphrase);
8788

88-
return sendForResult(METHOD_UNLOCK_KEY, List.of(name, passphrase), "unlock key " + name)
89+
// Empty passphrase is allowed - for keys stored without encryption
90+
String normalizedPassphrase = normalizePassphrase(passphrase);
91+
return sendForResult(METHOD_UNLOCK_KEY, List.of(name, normalizedPassphrase), "unlock key " + name)
8992
.thenApply(ignored -> Boolean.TRUE);
9093
}
9194

@@ -108,9 +111,9 @@ public CompletableFuture<BunkerKey> getKeyDetails(String name) {
108111
public CompletableFuture<BunkerKey> rotateKey(String oldName, String newName, String passphrase) {
109112
validateName(oldName);
110113
validateName(newName);
111-
requirePassphrase(passphrase);
112114

113-
return sendForKey(METHOD_ROTATE_KEY, List.of(oldName, newName, passphrase), newName);
115+
String normalizedPassphrase = normalizePassphrase(passphrase);
116+
return sendForKey(METHOD_ROTATE_KEY, List.of(oldName, newName, normalizedPassphrase), newName);
114117
}
115118

116119
private CompletableFuture<String> sendForResult(String method, List<String> params, String description) {
@@ -185,9 +188,14 @@ private void validateName(String name) {
185188
}
186189
}
187190

188-
private void requirePassphrase(String passphrase) {
189-
if (passphrase == null || passphrase.isBlank()) {
190-
throw new IllegalArgumentException("Passphrase must not be null or blank");
191-
}
191+
/**
192+
* Normalizes a passphrase to an empty string if null or blank.
193+
* This allows creating/unlocking keys without encryption.
194+
*
195+
* @param passphrase the passphrase to normalize
196+
* @return the passphrase or empty string if null/blank
197+
*/
198+
private String normalizePassphrase(String passphrase) {
199+
return passphrase != null && !passphrase.isBlank() ? passphrase : "";
192200
}
193201
}

nsecbunker-admin/src/test/java/xyz/tcheeric/nsecbunker/admin/key/DefaultKeyManagerTest.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,45 @@ void shouldRotateKey() throws Exception {
213213
assertThat(request.getParams()).containsExactlyElementsOf(List.of("cashu-old", "cashu-rotated", TEST_PASSPHRASE));
214214
}
215215

216+
/**
217+
* Ensures creating a key with null passphrase normalizes it to empty string.
218+
*/
219+
@Test
220+
void shouldCreateKeyWithNullPassphraseNormalizedToEmpty() {
221+
// Arrange
222+
String npub = "npub1nopwd";
223+
ArgumentCaptor<Nip46Request> requestCaptor = ArgumentCaptor.forClass(Nip46Request.class);
224+
when(adminClient.sendRequest(requestCaptor.capture()))
225+
.thenReturn(CompletableFuture.completedFuture(Nip46Response.success("1", npub)));
226+
227+
// Act
228+
BunkerKey result = keyManager.createKey("key-no-passphrase", null).join();
229+
230+
// Assert
231+
assertThat(result.getName()).isEqualTo("key-no-passphrase");
232+
Nip46Request request = requestCaptor.getValue();
233+
assertThat(request.getParams()).containsExactlyElementsOf(List.of("key-no-passphrase", ""));
234+
}
235+
236+
/**
237+
* Ensures unlocking a key with null passphrase normalizes it to empty string.
238+
*/
239+
@Test
240+
void shouldUnlockKeyWithNullPassphraseNormalizedToEmpty() {
241+
// Arrange
242+
ArgumentCaptor<Nip46Request> requestCaptor = ArgumentCaptor.forClass(Nip46Request.class);
243+
when(adminClient.sendRequest(requestCaptor.capture()))
244+
.thenReturn(CompletableFuture.completedFuture(Nip46Response.success("1", "ok")));
245+
246+
// Act
247+
boolean result = keyManager.unlockKey("key-unencrypted", null).join();
248+
249+
// Assert
250+
assertThat(result).isTrue();
251+
Nip46Request request = requestCaptor.getValue();
252+
assertThat(request.getParams()).containsExactlyElementsOf(List.of("key-unencrypted", ""));
253+
}
254+
216255
/**
217256
* Ensures NIP-46 errors are surfaced as AdminException through the future.
218257
*/

nsecbunker-client/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<parent>
99
<groupId>xyz.tcheeric</groupId>
1010
<artifactId>nsecbunker-java</artifactId>
11-
<version>0.1.0</version>
11+
<version>0.1.1</version>
1212
</parent>
1313

1414
<artifactId>nsecbunker-client</artifactId>

nsecbunker-connection/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<parent>
99
<groupId>xyz.tcheeric</groupId>
1010
<artifactId>nsecbunker-java</artifactId>
11-
<version>0.1.0</version>
11+
<version>0.1.1</version>
1212
</parent>
1313

1414
<artifactId>nsecbunker-connection</artifactId>

nsecbunker-core/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<parent>
99
<groupId>xyz.tcheeric</groupId>
1010
<artifactId>nsecbunker-java</artifactId>
11-
<version>0.1.0</version>
11+
<version>0.1.1</version>
1212
</parent>
1313

1414
<artifactId>nsecbunker-core</artifactId>

nsecbunker-monitoring/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<parent>
99
<groupId>xyz.tcheeric</groupId>
1010
<artifactId>nsecbunker-java</artifactId>
11-
<version>0.1.0</version>
11+
<version>0.1.1</version>
1212
</parent>
1313

1414
<artifactId>nsecbunker-monitoring</artifactId>

nsecbunker-protocol/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<parent>
99
<groupId>xyz.tcheeric</groupId>
1010
<artifactId>nsecbunker-java</artifactId>
11-
<version>0.1.0</version>
11+
<version>0.1.1</version>
1212
</parent>
1313

1414
<artifactId>nsecbunker-protocol</artifactId>

nsecbunker-spring-boot-starter/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<parent>
99
<groupId>xyz.tcheeric</groupId>
1010
<artifactId>nsecbunker-java</artifactId>
11-
<version>0.1.0</version>
11+
<version>0.1.1</version>
1212
</parent>
1313

1414
<artifactId>nsecbunker-spring-boot-starter</artifactId>

0 commit comments

Comments
 (0)