Skip to content

Commit f003825

Browse files
authored
chore: 🔧 Update PowerKV service (#27)
1 parent 28dbead commit f003825

File tree

1 file changed

+107
-15
lines changed

1 file changed

+107
-15
lines changed

config/pwrnosqldb/power_kv.go

Lines changed: 107 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package pwrnosqldb
33
import (
44
"bytes"
55
"context"
6+
"encoding/binary"
67
"encoding/hex"
78
"encoding/json"
89
"fmt"
@@ -12,6 +13,9 @@ import (
1213
"strconv"
1314
"strings"
1415
"time"
16+
17+
"golang.org/x/crypto/sha3"
18+
"github.com/pwrlabs/pwrgo/config/aes256"
1519
)
1620

1721
// PowerKvError represents errors from PowerKv operations
@@ -70,7 +74,7 @@ func NewPowerKv(projectID, secret string) (*PowerKv, error) {
7074

7175
return &PowerKv{
7276
client: client,
73-
serverURL: "https://pwrnosqlvida.pwrlabs.io/",
77+
serverURL: "https://powerkvbe.pwrlabs.io",
7478
projectID: projectID,
7579
secret: secret,
7680
}, nil
@@ -131,6 +135,66 @@ func (p *PowerKv) toBytes(data interface{}) ([]byte, error) {
131135
}
132136
}
133137

138+
// hash256 performs Keccak256 hash (PWRHash)
139+
func (p *PowerKv) hash256(input []byte) []byte {
140+
if input == nil {
141+
panic("Input is null") // or return error
142+
}
143+
hasher := sha3.NewLegacyKeccak256()
144+
hasher.Write(input)
145+
return hasher.Sum(nil)
146+
}
147+
148+
// packData packs key and data into binary format (ByteBuffer equivalent)
149+
func (p *PowerKv) packData(key, data []byte) []byte {
150+
var buf bytes.Buffer
151+
152+
// Write key length (4 bytes, big-endian) + key bytes
153+
binary.Write(&buf, binary.BigEndian, uint32(len(key)))
154+
buf.Write(key)
155+
156+
// Write data length (4 bytes, big-endian) + data bytes
157+
binary.Write(&buf, binary.BigEndian, uint32(len(data)))
158+
buf.Write(data)
159+
160+
return buf.Bytes()
161+
}
162+
163+
// unpackData unpacks binary data to get original key and data
164+
func (p *PowerKv) unpackData(packedBuffer []byte) ([]byte, []byte, error) {
165+
if len(packedBuffer) < 8 {
166+
return nil, nil, NewPowerKvError("InvalidInput", "Buffer too small for unpacking")
167+
}
168+
169+
buf := bytes.NewReader(packedBuffer)
170+
171+
// Read key length (4 bytes, big-endian)
172+
var keyLength uint32
173+
if err := binary.Read(buf, binary.BigEndian, &keyLength); err != nil {
174+
return nil, nil, NewPowerKvError("InvalidInput", fmt.Sprintf("Failed to read key length: %v", err))
175+
}
176+
177+
// Read key bytes
178+
key := make([]byte, keyLength)
179+
if _, err := buf.Read(key); err != nil {
180+
return nil, nil, NewPowerKvError("InvalidInput", fmt.Sprintf("Failed to read key: %v", err))
181+
}
182+
183+
// Read data length (4 bytes, big-endian)
184+
var dataLength uint32
185+
if err := binary.Read(buf, binary.BigEndian, &dataLength); err != nil {
186+
return nil, nil, NewPowerKvError("InvalidInput", fmt.Sprintf("Failed to read data length: %v", err))
187+
}
188+
189+
// Read data bytes
190+
data := make([]byte, dataLength)
191+
if _, err := buf.Read(data); err != nil {
192+
return nil, nil, NewPowerKvError("InvalidInput", fmt.Sprintf("Failed to read data: %v", err))
193+
}
194+
195+
return key, data, nil
196+
}
197+
134198
// Put stores data with the given key
135199
func (p *PowerKv) Put(key, data interface{}) (bool, error) {
136200
keyBytes, err := p.toBytes(key)
@@ -148,13 +212,25 @@ func (p *PowerKv) Put(key, data interface{}) (bool, error) {
148212

149213
// PutBytes stores byte data with byte key
150214
func (p *PowerKv) PutBytes(key, data []byte) (bool, error) {
215+
// Hash the key with Keccak256
216+
keyHash := p.hash256(key)
217+
218+
// Pack the original key and data
219+
packedData := p.packData(key, data)
220+
221+
// Encrypt the packed data
222+
encryptedData, err := aes256.Encrypt(packedData, p.secret)
223+
if err != nil {
224+
return false, NewPowerKvError("ServerError", fmt.Sprintf("Encryption failed: %v", err))
225+
}
226+
151227
url := p.serverURL + "/storeData"
152228

153229
payload := StoreDataRequest{
154230
ProjectID: p.projectID,
155231
Secret: p.secret,
156-
Key: p.toHexString(key),
157-
Value: p.toHexString(data),
232+
Key: p.toHexString(keyHash),
233+
Value: p.toHexString(encryptedData),
158234
}
159235

160236
jsonData, err := json.Marshal(payload)
@@ -186,16 +262,7 @@ func (p *PowerKv) PutBytes(key, data []byte) (bool, error) {
186262
return true, nil
187263
}
188264

189-
// Parse error message
190-
var errorResp ErrorResponse
191-
message := fmt.Sprintf("HTTP %d", resp.StatusCode)
192-
if err := json.Unmarshal(responseBody, &errorResp); err == nil && errorResp.Message != "" {
193-
message = errorResp.Message
194-
} else if len(responseBody) > 0 {
195-
message = fmt.Sprintf("HTTP %d — %s", resp.StatusCode, string(responseBody))
196-
}
197-
198-
return false, NewPowerKvError("ServerError", fmt.Sprintf("storeData failed: %s", message))
265+
return false, NewPowerKvError("ServerError", fmt.Sprintf("storeData failed: %d - %s", resp.StatusCode, string(responseBody)))
199266
}
200267

201268
// GetValue retrieves data for the given key
@@ -210,7 +277,9 @@ func (p *PowerKv) GetValue(key interface{}) ([]byte, error) {
210277

211278
// GetValueBytes retrieves data for the given byte key
212279
func (p *PowerKv) GetValueBytes(key []byte) ([]byte, error) {
213-
keyHex := p.toHexString(key)
280+
// Hash the key with Keccak256
281+
keyHash := p.hash256(key)
282+
keyHex := p.toHexString(keyHash)
214283
baseURL := p.serverURL + "/getValue"
215284

216285
params := url.Values{}
@@ -244,7 +313,30 @@ func (p *PowerKv) GetValueBytes(key []byte) ([]byte, error) {
244313
return nil, NewPowerKvError("ServerError", fmt.Sprintf("Unexpected response shape from /getValue: %s", string(responseBody)))
245314
}
246315

247-
return p.fromHexString(response.Value)
316+
// Handle both with/without 0x prefix
317+
cleanHex := response.Value
318+
if strings.HasPrefix(cleanHex, "0x") || strings.HasPrefix(cleanHex, "0X") {
319+
cleanHex = cleanHex[2:]
320+
}
321+
322+
encryptedValue, err := p.fromHexString(cleanHex)
323+
if err != nil {
324+
return nil, err
325+
}
326+
327+
// Decrypt the data
328+
decryptedData, err := aes256.Decrypt(encryptedValue, p.secret)
329+
if err != nil {
330+
return nil, NewPowerKvError("ServerError", fmt.Sprintf("Decryption failed: %v", err))
331+
}
332+
333+
// Unpack the data to get original key and data
334+
_, actualData, err := p.unpackData(decryptedData)
335+
if err != nil {
336+
return nil, err
337+
}
338+
339+
return actualData, nil
248340
}
249341

250342
// Parse error message

0 commit comments

Comments
 (0)